HarmonyOS實(shí)戰(zhàn)—滑動(dòng)事件的坐標(biāo)和返回值
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
Table of Contents
1. 滑動(dòng)事件獲取手指位置
2. 獲取按下時(shí)手指的位置(坐標(biāo))
3. 實(shí)現(xiàn)案例:把按下、移動(dòng)、松開(kāi)的位置分別設(shè)置到文本框當(dāng)中
4. 根據(jù)手指的位置來(lái)確定是上、下、左、右哪個(gè)滑動(dòng)
5. 滑動(dòng)事件bug處理
6. onTouchEvent方法的返回值
7. 驗(yàn)證onTouchEvent方法的返回值對(duì)滑動(dòng)事件三個(gè)動(dòng)作的影響
1. 滑動(dòng)事件獲取手指位置
- 滑動(dòng)事件的三個(gè)動(dòng)作:
- 獲取手指的位置就涉及到坐標(biāo)的概念,通過(guò)獲取到 x、y、z就可以缺任意一個(gè)點(diǎn)的位置
- 手機(jī)中的坐標(biāo):
- 除了 x、y軸,還有z軸,在鴻蒙手機(jī)當(dāng)中,完整的坐標(biāo)如下,是一個(gè)立體的三維體系,但平時(shí)z軸用的非常少,一般情況只需考慮x、y軸就行了。
- 結(jié)合滑動(dòng)事件的三個(gè)動(dòng)作和坐標(biāo)來(lái)分析滑動(dòng)
2. 獲取按下時(shí)手指的位置(坐標(biāo))
獲取的這些數(shù)據(jù)其實(shí)都被鴻蒙操作系統(tǒng)封裝到TouchEvent這個(gè)動(dòng)作對(duì)象當(dāng)中,通過(guò)動(dòng)作去調(diào)用getPointerPosition 方法,需要傳遞一個(gè)值。鴻蒙系統(tǒng)支持多手指的操作,比如:可以用兩個(gè)手指對(duì)圖片進(jìn)行放大或縮小,所以在getPointerPosition需要傳遞一個(gè)索引,一個(gè)手指操作傳遞的值為0,表示要獲取的是第一個(gè)手指的位置,他的位置也是封裝成一個(gè)對(duì)象,再用坐標(biāo)對(duì)象分別獲取到x、y坐標(biāo)。
- //獲取按下時(shí)手指的位置(坐標(biāo))
- MmiPoint point = touchEvent.getPointerPosition(0);
- //x、y表示按下時(shí)手指的位置
- float x = point.getX();
- float y = point.getY();
- text1.setText(x + "---" + y);
3. 實(shí)現(xiàn)案例:把按下、移動(dòng)、松開(kāi)的位置分別設(shè)置到文本框當(dāng)中
- 新建項(xiàng)目:ListenerApplication4
ability_main
- 采用默認(rèn)生成的Text文本內(nèi)容,在此基礎(chǔ)上給DirectionalLayout布局和Text組件分別加上id
- <?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:background_element="$graphic:background_ability_main"
- ohos:layout_alignment="horizontal_center"
- ohos:text="$string:mainability_HelloWorld"
- ohos:text_size="40vp"
- />
- </DirectionalLayout>
MainAbilitySlice
- 采用當(dāng)前類作為實(shí)現(xiàn)類接口的方式編寫(xiě)
- package com.xdr630.listenerapplication.slice;
- import com.xdr630.listenerapplication.ResourceTable;
- import ohos.aafwk.ability.AbilitySlice;
- import ohos.aafwk.content.Intent;
- 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 text1 = null;
- @Override
- public void onStart(Intent intent) {
- super.onStart(intent);
- super.setUIContent(ResourceTable.Layout_ability_main);
- //1.先找到整個(gè)布局對(duì)象
- DirectionalLayout dl = (DirectionalLayout) findComponentById(ResourceTable.Id_dl);
- text1 = (Text) findComponentById(ResourceTable.Id_text1);
- //2.給整個(gè)布局添加滑動(dòng)事件
- //當(dāng)我們?cè)谡麄€(gè)布局滑動(dòng)的時(shí)候,就會(huì)調(diào)用本類中的onTouchEvent方法
- //在按下 移動(dòng)、松開(kāi)的過(guò)程,代碼會(huì)不斷去調(diào)用本類中的 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) {
- //參數(shù)1:component表示滑動(dòng)的組件(布局也是一種組件,所以也可以用component表示布局對(duì)象)
- //實(shí)際上此時(shí)代表的就是DirectionalLayout布局對(duì)象,這個(gè)布局是鋪滿整個(gè)屏幕的
- //參數(shù)2:touchEvent表示動(dòng)作對(duì)象(按下、滑動(dòng)、抬起)
- //獲取當(dāng)前手指對(duì)屏幕進(jìn)行操作(按下、滑動(dòng)、抬起)
- int action = touchEvent.getAction();
- // 1:表示按下操作
- // 2:表示松開(kāi)操作
- // 3. 表示滑動(dòng)/移動(dòng)操作
- if (action == TouchEvent.PRIMARY_POINT_DOWN){
- //只要寫(xiě)按下時(shí)需要運(yùn)行的代碼即可
- //獲取按下時(shí)手指的位置(坐標(biāo))
- MmiPoint point = touchEvent.getPointerPosition(0);
- //x、y表示按下時(shí)手指的位置
- float x = point.getX();
- float y = point.getY();
- text1.setText(x + "---" + y);
- }else if (action == TouchEvent.POINT_MOVE){
- //移動(dòng)或滑動(dòng)
- //獲取按下時(shí)手指的位置(坐標(biāo))
- MmiPoint point = touchEvent.getPointerPosition(0);
- //x、y表示按下時(shí)手指的位置
- float x = point.getX();
- float y = point.getY();
- text1.setText(x + "---" + y);
- }else if (action == TouchEvent.PRIMARY_POINT_UP){
- //松開(kāi)或抬起
- //獲取按下時(shí)手指的位置(坐標(biāo))
- MmiPoint point = touchEvent.getPointerPosition(0);
- //x、y表示按下時(shí)手指的位置
- float x = point.getX();
- float y = point.getY();
- text1.setText(x + "---" + y);
- }
- return true;
- }
- }
- 運(yùn)行:
- 按下并且移動(dòng)鼠標(biāo)時(shí),坐標(biāo)數(shù)值就會(huì)隨著鼠標(biāo)的移動(dòng)而變化
4. 根據(jù)手指的位置來(lái)確定是上、下、左、右哪個(gè)滑動(dòng)
首先把按下時(shí)的 x、y 移動(dòng)onTouchEvent方法外面去,因?yàn)槿绻麤](méi)有移動(dòng)外面去,當(dāng)?shù)谝淮伟聪碌臅r(shí)候就會(huì)調(diào)用onTouchEvent方法,接著就會(huì)調(diào)用按下時(shí)的位置,獲取到x、y坐標(biāo)并設(shè)置到文本框里,設(shè)置完以后整個(gè)方法就么有了,獲取完后就從內(nèi)存中消失了,按下時(shí)的x、y的值也就消失了。
所以在方法外定義x、y,因?yàn)楂@取到的是小數(shù),要定義為float類型
移動(dòng)的位置就不需要獲取了,只要按下和松開(kāi)的位置進(jìn)行對(duì)比就可以判斷是上、下、左、右的哪個(gè)滑動(dòng)了
- 右滑
- 下滑
- 把上述代碼進(jìn)行如下修改
- 在onTouchEvent方法外定義x、y的位置
- //記錄按下手指的位置
- float startX = 0;
- float startY = 0;
- 在onTouchEvent方法里的if判斷作出如下修改
- if (action == TouchEvent.PRIMARY_POINT_DOWN){
- MmiPoint point = touchEvent.getPointerPosition(0);
- //x、y表示按下時(shí)手指的位置
- startX = point.getX();
- startY = point.getY();
- }else if (action == TouchEvent.POINT_MOVE){
- //移動(dòng)的位置就不需要獲取了,只要按下和松開(kāi)的位置進(jìn)行對(duì)比就可以判斷是上、下、左、右的哪個(gè)滑動(dòng)了
- }else if (action == TouchEvent.PRIMARY_POINT_UP){
- //松開(kāi)或抬起
- MmiPoint point = touchEvent.getPointerPosition(0);
- //x、y表示按下時(shí)手指的位置
- float endX = point.getX();
- float endY = point.getY();
- //拿著按下時(shí)的位置跟松開(kāi)時(shí)手指的位置進(jìn)行比對(duì)
- if (endX > startX){
- text1.setText("右滑");
- }else if (endX < startX){
- text1.setText("左滑");
- }else if (endY > startY){
- text1.setText("下滑");
- }else if (endY < startY) {
- text1.setText("上滑");
- }
- 運(yùn)行:
- 按下后鼠標(biāo)從左往右移動(dòng),然后松開(kāi)
- 按下后鼠標(biāo)從右往左移動(dòng),然后松開(kāi)
- 按下后鼠標(biāo)從上往下移動(dòng),然后松開(kāi)
- 按下后鼠標(biāo)從下往上移動(dòng),然后松開(kāi)
- 此時(shí)還有一個(gè)明顯的bug,那就是當(dāng)鼠標(biāo)從最最左邊上面的點(diǎn)到最右邊下面的點(diǎn),既有下滑也有右滑
5. 滑動(dòng)事件bug處理
- 當(dāng)我們滑動(dòng)的時(shí)候,滑的不直,滑的有點(diǎn)斜
- 斜著滑,可以對(duì)Y變化的范圍(斜的幅度)做一個(gè)規(guī)定,假設(shè)變化為100,如果你滑的時(shí)候變化了超過(guò)了100,那就認(rèn)為這是一個(gè)無(wú)效的滑動(dòng),如果沒(méi)有超過(guò),才認(rèn)為這是一個(gè)有效的滑動(dòng)
- 解決bug:
添加個(gè)絕對(duì)值,防止兩者大小相減出現(xiàn)復(fù)數(shù)
- if (endX > startX && Math.abs(endY - startY) < 100){
- text1.setText("右滑");
- }else if (endX < startX && Math.abs(endY - startY) < 100){
- text1.setText("左滑");
- }else if (endY > startY && Math.abs(endX - startX) < 100){
- text1.setText("下滑");
- }else if (endY < startY && Math.abs(endX - startX) < 100) {
- text1.setText("上滑");
- }
- 運(yùn)行,當(dāng)斜的幅度超過(guò)100時(shí),就會(huì)認(rèn)為這是個(gè)無(wú)效的滑動(dòng),就不會(huì)顯示這個(gè)滑動(dòng)的動(dòng)作
- 但運(yùn)行斜的幅度不超過(guò)100,就會(huì)顯示正確的滑動(dòng)效果
6. onTouchEvent方法的返回值
- 如果為true,表示所有的動(dòng)作都會(huì)觸發(fā)當(dāng)前方法并執(zhí)行對(duì)應(yīng)的代碼
- 如果為false,表示只有一個(gè)動(dòng)作會(huì)觸發(fā)當(dāng)前方法并執(zhí)行對(duì)應(yīng)的代碼,后續(xù)的動(dòng)作就不會(huì)觸發(fā)當(dāng)前方法
- 滑動(dòng)事件的三個(gè)動(dòng)作:按下——>移動(dòng)——>松開(kāi),當(dāng)為true時(shí),這三個(gè)動(dòng)作都會(huì)執(zhí)行onTouchEvent方法并執(zhí)行下面對(duì)應(yīng)的代碼。為false時(shí),只有按下這個(gè)動(dòng)作會(huì)觸發(fā) onTouchEvent方法并執(zhí)行下面對(duì)應(yīng)的代碼
7. 驗(yàn)證onTouchEvent方法的返回值對(duì)滑動(dòng)事件三個(gè)動(dòng)作的影響
上述代碼不變,onTouchEvent方法改動(dòng)如下:
- public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
- count++;
- int action = touchEvent.getAction();
- if (action == TouchEvent.PRIMARY_POINT_DOWN){
- text1.setText("按下");
- }else if (action == TouchEvent.POINT_MOVE){
- text1.setText("移動(dòng)");
- }else if (action == TouchEvent.PRIMARY_POINT_UP){
- text1.setText("松開(kāi)");
- }
- //如果為true,表示所有的動(dòng)作都會(huì)觸發(fā)當(dāng)前方法并執(zhí)行對(duì)應(yīng)的代碼
- //如果為false,表示只有一個(gè)動(dòng)作會(huì)觸發(fā)當(dāng)前方法并執(zhí)行對(duì)應(yīng)的代碼,后續(xù)的動(dòng)作就不會(huì)觸發(fā)當(dāng)前方法了
- return false;
- }
運(yùn)行后,當(dāng)按下后再移動(dòng)、松開(kāi)。顯示的文本依賴不變,說(shuō)明返回值為false,只有按下這個(gè)動(dòng)作會(huì)觸發(fā) onTouchEvent方法并執(zhí)行下面對(duì)應(yīng)的代碼,移動(dòng)、松開(kāi)都不會(huì)執(zhí)行onTouchEvent方法。
把上面的返回值改為true,運(yùn)行后。發(fā)現(xiàn)文本顯示的值都會(huì)隨著按下、移動(dòng)、松開(kāi)的動(dòng)作進(jìn)行變化。
所以滑動(dòng)事件一般都寫(xiě)true。
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)