根据手指按下位置和手指抬起位置,就可以判断是上移还是下移,左滑还是右滑。
注:移动事件是相对于 DirectionalLayout而言的,所以首先需要给DirectionalLayout设置ID为了后期使用的时候获取到布局组件。
一、案例分析
XML中组件的定义:
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
ohos:id="$+id:dl"
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:alignment="center"
ohos:orientation="vertical">
<Text
ohos:id="$+id:text1"
ohos:height="match_content"
ohos:width="match_content"
ohos:text="原始文字"
ohos:text_size="100"
/>
</DirectionalLayout>
MainAbilitySlice类定义了具体的操作流程:
package com.example.clickthings.slice;
import com.example.clickthings.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Text;
import ohos.multimodalinput.event.TouchEvent;
public class MainAbilitySlice extends AbilitySlice implements Component.TouchEventListener {
Text text = null;
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
//1、查找布局和文本框组件
text = (Text)findComponentById(ResourceTable.Id_text1);
DirectionalLayout dl = (DirectionalLayout) findComponentById(ResourceTable.Id_dl);
//2、给整个布局组件绑定事件触摸事件
//当在整个布局上滑动的时候,就会调用本类中的onTouchEvent方法
//在按下、移动、松开的过程中,代码会不断的去调用本类中的onTouchEvent方法
dl.setTouchEventListener(this);
}
@Override
public void onActive() {
super.onActive();
}
@Override
public void onForeground(Intent intent) {
super.onForeground(intent);
}
@Override
public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
//参数1:component表示滑动的那个组件(布局也是一种组件)
//实际上此时代表的就是那个DirectionalLayout这个布局对象
//参数2:touchEvent动作对象(按下、滑动、抬起)
//获取当前手指对屏幕进行的操作(按下、滑动、抬起)
int action = touchEvent.getAction();
// 1 PRIMARY_POINT_DOWN 表示按下操作
// 2 PRIMARY_POINT_UP 表示松开操作
// 3 POINT_MOVE 表示滑动/移动操作
if(action == TouchEvent.PRIMARY_POINT_DOWN) {
//写按下时需要运行的代码
text.setText("按下操作");
} else if(action == TouchEvent.POINT_MOVE) {
//移动 | 滑动
text.setText("移动/滑动操作");
} else if(action == TouchEvent.PRIMARY_POINT_UP) {
//抬起手指
text.setText("抬起手指");
}
return true;
}
}
二、手机中的坐标
三、上下左右滑动
拿着按下时手指的位置和抬起时的位置进行比对:
- 落下时X坐标大于起始的X坐标就为右移,否则左移
- 落下时Y坐标大于起始的Y坐标就为下移,否则上移
package com.example.clickthings.slice;
import com.example.clickthings.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Text;
import ohos.agp.utils.Point;
import ohos.multimodalinput.event.MmiPoint;
import ohos.multimodalinput.event.TouchEvent;
public class MainAbilitySlice extends AbilitySlice implements Component.TouchEventListener {
//文本组件对象
Text text = null;
//记录刚开始按下时的坐标
float startX = 0;
float startY = 0;
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
//1、查找布局和文本框组件
text = (Text)findComponentById(ResourceTable.Id_text1);
DirectionalLayout dl = (DirectionalLayout) findComponentById(ResourceTable.Id_dl);
//2、给整个布局组件绑定事件触摸事件
//当在整个布局上滑动的时候,就会调用本类中的onTouchEvent方法
//在按下、移动、松开的过程中,代码会不断的去调用本类中的onTouchEvent方法
dl.setTouchEventListener(this);
}
@Override
public void onActive() {
super.onActive();
}
@Override
public void onForeground(Intent intent) {
super.onForeground(intent);
}
@Override
public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
//参数1:component表示滑动的那个组件(布局也是一种组件)
//实际上此时代表的就是那个DirectionalLayout这个布局对象
//参数2:touchEvent动作对象(按下、滑动、抬起)
//获取当前手指对屏幕进行的操作(按下、滑动、抬起)
int action = touchEvent.getAction();
// 1 PRIMARY_POINT_DOWN 表示按下操作
// 2 PRIMARY_POINT_UP 表示松开操作
// 3 POINT_MOVE 表示滑动/移动操作
if(action == TouchEvent.PRIMARY_POINT_DOWN) {
//获取按下时手指的位置(坐标)
MmiPoint point = touchEvent.getPointerPosition(0); //一个手指
startX = point.getX();
startY = point.getY();
} else if(action == TouchEvent.POINT_MOVE) {
//移动 | 滑动
text.setText("移动/滑动操作");
} else if(action == TouchEvent.PRIMARY_POINT_UP) {
//获取抬起时的坐标
MmiPoint point = touchEvent.getPointerPosition(0);
float endX = point.getX();
float endY = point.getY();
//拿着按下时手指的位置和抬起时的位置进行比对
//落下时X坐标大于起始的X坐标就为右移,否则左移
//落下时Y坐标大于起始的Y坐标就为下移,否则上移
if(endX > startX) {
text.setText("右滑");
} else if(endX < startX) {
text.setText("左滑");
} else if(endY > startY) {
text.setText("下滑");
} else if(endY < startY) {
text.setText("上滑");
}
}
return true;
}
}
以上代码bug解决:
滑动必须直直的滑动,稍微有倾斜,会出现判断错误。因此需要作限制判断,如果判断是否是左右移动,这个时候X变化的同时,变化前后的Y的差值不能不超过100即为合理范围,
左右滑动:Math.abs(endY - startY) < 100
上下滑动:Math.abs(endX - startX) < 100
package com.example.clickthings.slice;
import com.example.clickthings.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Text;
import ohos.agp.utils.Point;
import ohos.multimodalinput.event.MmiPoint;
import ohos.multimodalinput.event.TouchEvent;
public class MainAbilitySlice extends AbilitySlice implements Component.TouchEventListener {
//文本组件对象
Text text = null;
//记录刚开始按下时的坐标
float startX = 0;
float startY = 0;
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
//1、查找布局和文本框组件
text = (Text)findComponentById(ResourceTable.Id_text1);
DirectionalLayout dl = (DirectionalLayout) findComponentById(ResourceTable.Id_dl);
//2、给整个布局组件绑定事件触摸事件
//当在整个布局上滑动的时候,就会调用本类中的onTouchEvent方法
//在按下、移动、松开的过程中,代码会不断的去调用本类中的onTouchEvent方法
dl.setTouchEventListener(this);
}
@Override
public void onActive() {
super.onActive();
}
@Override
public void onForeground(Intent intent) {
super.onForeground(intent);
}
@Override
public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
//参数1:component表示滑动的那个组件(布局也是一种组件)
//实际上此时代表的就是那个DirectionalLayout这个布局对象
//参数2:touchEvent动作对象(按下、滑动、抬起)
//获取当前手指对屏幕进行的操作(按下、滑动、抬起)
int action = touchEvent.getAction();
// 1 PRIMARY_POINT_DOWN 表示按下操作
// 2 PRIMARY_POINT_UP 表示松开操作
// 3 POINT_MOVE 表示滑动/移动操作
if(action == TouchEvent.PRIMARY_POINT_DOWN) {
//获取按下时手指的位置(坐标)
MmiPoint point = touchEvent.getPointerPosition(0); //一个手指
startX = point.getX();
startY = point.getY();
} else if(action == TouchEvent.POINT_MOVE) {
//移动 | 滑动
text.setText("移动/滑动操作");
} else if(action == TouchEvent.PRIMARY_POINT_UP) {
//获取抬起时的坐标
MmiPoint point = touchEvent.getPointerPosition(0);
float endX = point.getX();
float endY = point.getY();
//拿着按下时手指的位置和抬起时的位置进行比对
//落下时X坐标大于起始的X坐标就为右移,否则左移
//落下时Y坐标大于起始的Y坐标就为下移,否则上移
if(endX > startX && Math.abs(endY - startY) < 100) {
text.setText("右滑");
} else if(endX < startX && Math.abs(endY - startY) < 100) {
text.setText("左滑");
} else if(endY > startY && Math.abs(endX - startX) < 100) {
text.setText("下滑");
} else if(endY < startY && Math.abs(endX - startX) < 100) {
text.setText("上滑");
}
}
return true;
}
}
四、onTouchEvent返回值
- 如果为true,表示所有的动作都会出发当前方法并执行对应代码
- 如果为false,表示只有第一个动作会触发当前方法并执行对应代码,后续的动作就不会触发当前对应代码了