成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

鴻蒙開源第三方組件—自定義圖片縮放組件PinchImageView-ohos

系統
文章由鴻蒙社區產出,想要了解更多內容請前往:51CTO和華為官方戰略合作共建的鴻蒙技術社區https://harmonyos.51cto.com

[[406187]]

想了解更多內容,請訪問:

51CTO和華為官方合作共建的鴻蒙技術社區

https://harmonyos.51cto.com

前言

基于安卓平臺的手勢操控組件PinchImageView-ohos(https://github.com/boycy815/PinchImageView), 實現鴻蒙的功能化遷移和重構。代碼已經開源到(https://gitee.com/isrc_ohos/pinch-image-view-ohos),歡迎各位開發者提出寶貴意見。

背景

PinchImageView-ohos是一個支持多點觸控的ImageView手勢操控組件,通過識別單指雙擊、雙指捏合、單指滑動等手勢指令,實現圖片的放大、縮小、滑動等效果。該組件功能豐富且使用簡單,被廣泛應用于各類圖片預覽類應用。

組件效果展示

1、雙指相向或相對捏合,實現圖片的縮放變化。

鴻蒙開源第三方組件——自定義圖片縮放組件PinchImageView-ohos -鴻蒙HarmonyOS技術社區

圖1.雙指捏合效果

2、單指雙擊實現圖片的放大縮小。

鴻蒙開源第三方組件——自定義圖片縮放組件PinchImageView-ohos -鴻蒙HarmonyOS技術社區

圖2 雙擊效果

3、單指雙擊后單指移動,實現圖片的放大后平移。

鴻蒙開源第三方組件——自定義圖片縮放組件PinchImageView-ohos -鴻蒙HarmonyOS技術社區

圖3 單指雙擊后單指移動效果

Sample解析

Sample部分主要負責整體顯示布局的搭建。首先為PinchImageView-ohos組件設置顯示圖片,然后將組件對象添加到顯示布局中。下面將詳細介紹組件的使用方法。

步驟1. 創建整體的顯示布局。

步驟2. 導入相關類并實例化PinchImageView-ohos組件對象。

步驟3. 設置顯示圖片。

步驟4. 將PinchImageView-ohos組件對象添加到整體顯示布局中。

  1. //步驟1 創建整體的顯示布局 
  2. DirectionalLayout directionalLayout = new DirectionalLayout(this); 
  3.  
  4. //步驟2 導入相關類并實例化對象 
  5. PinchImageViewnew pinchImageView = new PinchImageViewnew(this); 
  6.  
  7. //步驟3 設置顯示圖片 
  8. pinchImageView.setPixelMap(this, ResourceTable.Media_1111); 
  9.  
  10. //步驟4 將pinchImageView添加到整體顯示布局中 
  11. directionalLayout.addComponent(pinchImageView); 
  12. setUIContent(directionalLayout); 

Library解析

Library主要為PinchImageView-ohos組件實現手勢獲取功能和圖片操控功能。

開發者通過設置監聽器來捕捉各類手勢,根據不同的手勢執行不同的圖片操控方法,從而顯示不同的圖片操控效果,如放大、縮小、移動。

1、手勢獲取方法

手勢獲取對實現PinchImageView-ohos組件的功能尤為重要,此處主要通過onTouchEvent()方法來捕捉對應的手勢。主要用到的手勢包含PRIMARY_POINT_UP(最后一根手指從屏幕上抬起)、PRIMARY_POINT_DOWN(第一根手指觸摸屏幕)、OTHER_POINT_DOWN(當一根或多根手指已經觸摸屏幕時,另一個手指觸摸屏幕 )、OTHER_POINT_UP(一些手指從屏幕上抬起,而一些手指仍留在屏幕上 )、POINT_MOVE(手指在屏幕上移動)。通過監控各類手勢的操作順序和觸碰時間等條件,達到識別捏合、滑動、單擊、雙擊等復雜手勢的效果。

onTouchEvent()函數首先通過TouchEvent.getAction()方法獲取當前的手勢,當手勢為:

(1)PRIMARY_POINT_UP

需要判斷圖片之前是否處于縮放模式(此時圖片處于縮放狀態)。如果是縮放模式,則觸發結束縮放動畫,后將手勢狀態置于自由模式。

  1. //最后一個點抬起或者取消,結束所有模式 
  2. if (action == TouchEvent.PRIMARY_POINT_UP || action == TouchEvent.CANCEL) { 
  3.     //如果之前是縮放模式,還需要結束縮放動畫 
  4.     if (mPinchMode == PINCH_MODE_SCALE) { 
  5.         scaleEnd();//縮放結束 
  6.     } 
  7.     //手勢狀態置于自由模式 
  8.     mPinchMode = PINCH_MODE_FREE; 
  9.  } 

(2)PRIMARY_POINT_DOWN

需要判斷圖片是否在縮放動畫中,若不在,圖片將切換到滾動模式(此時圖片處于可自由移動狀態),并保存觸發點的位置,用于(5)中的計算。

  1. else if (action == TouchEvent.PRIMARY_POINT_DOWN) { 
  2.     //在縮放動畫過程中不允許啟動滾動模式 
  3.     if (!(mScaleAnimator != null && mScaleAnimator.isRunning())) { 
  4.         //在動畫過程中不允許啟動滾動模式,停止所有動畫 
  5.         cancelAllAnimator(); 
  6.         //切換到滾動模式 
  7.         mPinchMode = PINCH_MODE_SCROLL; 
  8.         //保存觸發點的位置用于(5)中的計算 
  9.         mLastMovePoint.modify(event.getPointerPosition(0).getX(), event.getPointerPosition(0).getY());                   
  10.         } 

(3)OTHER_POINT_DOWN

需要將圖片模式切換到縮放模式,并保存兩個觸發點的位置,用于(5)中的計算。

  1. else if (action == TouchEvent.OTHER_POINT_DOWN) { 
  2.     //在動畫過程中不允許啟動縮放模式,停止所有動畫 
  3.     cancelAllAnimator(); 
  4.     //切換到縮放模式 
  5.     mPinchMode = PINCH_MODE_SCALE; 
  6.     //保存縮放的兩個觸發點的位置,用于(5)中的計算 
  7.     saveScaleContext(event.getPointerPosition(0).getX(), event.getPointerPosition(0).getY(), event.getPointerPosition(1).getX(), event.getPointerPosition(1).getY()); 
  8. }  

(4)OTHER_POINT_UP

需要判斷手指抬起后圖片是否處于縮放模式。

如果處于縮放模式下,判斷識別到的手指是否超過兩個。

在剩余手指超過兩個(縮放模式未結束)的情況下,第一個觸摸的手指抬起,

那么讓第二個觸摸的手指和第三個觸摸的手指所在的點作為縮放控制點。

在剩余手指超過兩個(縮放模式未結束)的情況下,第二個觸摸的手指抬起,

那么讓第一個觸摸的手指和第三個觸摸的手指所在的點作為縮放控制點。

如果處于縮放模式下,判斷識別到的手指只有一個。此時不能允許它切換到滾動模式,因為圖片可能沒有在初始的位置上。

手指抬起后圖片未處于縮放模式時(屏幕上僅剩余一個手指),開啟滾動模式,并記錄開始滾動的點。

  1. else if (action == TouchEvent.OTHER_POINT_UP) { 
  2.     //多個手指情況下抬起一個手指,此時需要是縮放模式才觸發 
  3.     if (mPinchMode == PINCH_MODE_SCALE) { 
  4.         //抬起的點如果大于2,那么縮放模式還有效,但是有可能初始點變了,重新測量初始點 
  5.         if (event.getPointerCount() > 2) { 
  6.           //如果還沒結束縮放模式,但是第一個點抬起了,那么讓第二個點和第三個點作為縮放控制點 
  7.             if (event.getAction() >> 8 == 0) { 
  8.                 event.getPointerPosition(1).getX(); 
  9.                 saveScaleContext(event.getPointerPosition(1).getX(), event.getPointerPosition(1).getY(), event.getPointerPosition(2).getX(), event.getPointerPosition(2).getY()); 
  10.           //如果還沒結束縮放模式,但是第二個點抬起了,那么讓第一個點和第三個點作為縮放控制點 
  11.             } else if (event.getAction() >> 8 == 1) { 
  12.                 saveScaleContext(event.getPointerPosition(0).getX(), event.getPointerPosition(0).getY(), event.getPointerPosition(2).getX(), event.getPointerPosition(2).getY()); 
  13.             } 
  14.         } 
  15.         //如果抬起的點等于2,那么此時只剩下一個點,也不允許進入單指模式,因為此時可能圖片沒有在正確的位置上 
  16.     } 

(5)POINT_MOVE

需要判斷當前圖片的模式。當為滾動模式時,執行scrollBy()方法來實現圖片的移動效果;當它為縮放模式時,計算兩個縮放點的距離和縮放點的中心,并執行scale()方法實現圖片的縮放效果。scrollBy()方法和scale()方法的具體邏輯在圖片操控方法中有詳細介紹,此處就不做過多贅述。

  1. else if (action == TouchEvent.POINT_MOVE) { 
  2.     if (!(mScaleAnimator != null && mScaleAnimator.isRunning())) { 
  3.         //在滾動模式下移動 
  4.         if (mPinchMode == PINCH_MODE_SCROLL) { 
  5.             //每次移動產生一個差值累積到圖片位置上 
  6.             scrollBy(event.getPointerPosition(0).getX() - mLastMovePoint.position[0], event.getPointerPosition(0).getY() - mLastMovePoint.position[1]); 
  7.             //記錄新的移動點 
  8.             mLastMovePoint.modify(event.getPointerPosition(0).getX(), event.getPointerPosition(0).getY()); 
  9.             //在縮放模式下移動 
  10.         } else if (mPinchMode == PINCH_MODE_SCALE && event.getPointerCount() > 1) { 
  11.             //兩個縮放點間的距離 
  12.             float distance = MathUtils.getDistance(event.getPointerPosition(0).getX(), event.getPointerPosition(0).getY(), event.getPointerPosition(1).getX(), event.getPointerPosition(1).getY()); 
  13.             //保存縮放點中心 
  14.             float[] lineCenter = MathUtils.getCenterPoint(event.getPointerPosition(0).getX(), event.getPointerPosition(0).getY(), event.getPointerPosition(1).getX(), event.getPointerPosition(1).getY()); 
  15.             mLastMovePoint.modify(lineCenter[0], lineCenter[1]);                                     
  16.             //處理縮放 
  17.             scale(mScaleCenter, mScaleBase, distance, mLastMovePoint); 
  18.         } 
  19.     } 

2、圖片操控方法

圖片縮放

(1)雙指捏合

雙指捏合,顧名思義是表示兩根手指向相反方向移動的操作,該操作可實現圖片放大縮小的效果。雙指捏合完成圖片縮放的功能是由scale()方法實現的。

在scale()方法體中需要設置各種縮放參數:scaleBase是縮放系數、scaleCenter代表圖片縮放中點、distance指兩指間距離、lineCenter是兩指中點。scaleBase和distance相乘會得到縮放比例,圖片依舊縮放比例進行變化。在縮放過程中,圖片縮放中點scaleCenter會跟隨兩指中點lineCenter移動,實現以兩指中點為中心對圖片進行放大縮小的效果,縮放效果如圖4所示。

鴻蒙開源第三方組件——自定義圖片縮放組件PinchImageView-ohos -鴻蒙HarmonyOS技術社區

圖4 圖片雙指縮放

  1. private void scale(Point scaleCenter, float scaleBase, float distance, Point lineCenter) { 
  2.     if (!isReady()) { 
  3.         return
  4.     } 
  5.     //計算圖片從fit center狀態到目標狀態的縮放比例 
  6.     float scale = scaleBase * distance; 
  7.     Matrix matrix = MathUtils.matrixTake(); 
  8.     //按照圖片縮放中心縮放,并且讓縮放中心在縮放點中點上 
  9.     matrix.postScale(scale, scale,  scaleCenter.position[0], scaleCenter.position[1]); 
  10.     //讓圖片的縮放中點跟隨手指縮放中點 
  11.     matrix.postTranslate(lineCenter.position[0] - scaleCenter.position[0], lineCenter.position[1] - scaleCenter.position[1]); 
  12.     //應用變換 
  13.     mOuterMatrix.setMatrix(matrix); 
  14.     MathUtils.matrixGiven(matrix); 
  15.     dispatchOuterMatrixChanged(); 
  16.     //重繪 
  17.     invalidate(); 

(2)單指雙擊

單指雙擊表示用單根手指雙擊屏幕的操作,該操作可實現圖片放大縮小的效果,單指雙擊完成圖片縮放的功能是由doubleTap()方法實現的。

在doubleTap()方法體中我們初始化了一個縮放動畫的對象mScaleAnimator(),它有兩個參數分別為mOuterMatrix(開始矩陣)和animEnd(結束矩陣)。開始矩陣表示圖片原來的位置與大小;結束矩陣表示圖片縮放后的位置與大小,是根據放大比例和雙擊點位置確定的。確定圖片的開始和結束矩陣后,啟動縮放動畫,便可以實現縮放效果,如圖5所示。

鴻蒙開源第三方組件——自定義圖片縮放組件PinchImageView-ohos -鴻蒙HarmonyOS技術社區

圖5 單點觸摸雙擊縮放

  1. private void doubleTap(float x, float y) { 
  2.     ... 
  3.     //開始計算縮放動畫的結果矩陣 
  4.     Matrix animEnd = MathUtils.matrixTake(mOuterMatrix); 
  5.     //計算還需縮放的倍數 
  6.     animEnd.postScale(nextScale / currentScale, nextScale / currentScale, x, y); 
  7.     //將放大點移動到控件中心 
  8.     animEnd.postTranslate(displayWidth / 2f - x, displayHeight / 2f - y); 
  9.     RectFloat testBound = MathUtils.rectFTake(0,0,mp.getImageInfo().size.width,mp.getImageInfo().size.height); 
  10.     ... 
  11.     //清理當前可能正在執行的動畫 
  12.     cancelAllAnimator(); 
  13.     //啟動矩陣動畫 
  14.     mScaleAnimator = new ScaleAnimator(mOuterMatrix, animEnd); 
  15.     mScaleAnimator.start(); 
  16.     ... 

圖片在縮放狀態下移動

單指滑動表示手指在屏幕上完成矢量平移,是圖片移動的唯一方式。該功能是通過scrollBy()方法實現的。

以實現圖片左右移動為例,在scrollBy()方法中,需要判斷縮放狀態下圖片位移的最大距離,有以下幾種不同的情況:

  • 圖片移動后,左側邊緣超出控件的左側邊緣,圖片無法移動;
  • 圖片移動后,右側邊緣超出控件的右側邊緣,圖片無法移動;
  • 圖片移動后,兩側都未超出控件邊緣的情況下,將以手指觸碰點作為控制點,對圖片進行水平移動。

圖片上下平移的情況與左右平移類似,這里不做贅述,圖片移動效果如圖6所示。

鴻蒙開源第三方組件——自定義圖片縮放組件PinchImageView-ohos -鴻蒙HarmonyOS技術社區

圖6 圖片移動的最大距離

  1. public boolean scrollBy(float xDiff, float yDiff) { 
  2. ... 
  3.  if (bound.right - bound.left < displayWidth) { 
  4.      xDiff = 0; 
  5.    //如果圖片左邊在移動后超出控件左邊 
  6.  } else if (bound.left + xDiff > 0) { 
  7.    //如果在移動之前是沒超出的,計算應該移動的距離 
  8.      if (bound.left < 0) { 
  9.          xDiff = -bound.left
  10.    //否則無法移動 
  11.      } else { 
  12.          xDiff = 0; 
  13.      } 
  14.    //如果圖片右邊在移動后超出控件右邊 
  15.  } else if (bound.right + xDiff < displayWidth) { 
  16.    //如果在移動之前是沒超出的,計算應該移動的距離 
  17.      if (bound.right > displayWidth) { 
  18.          xDiff = displayWidth - bound.right
  19.     //否則無法移動 
  20.      } else { 
  21.          xDiff = 0; 
  22.      } 
  23.  } 
  24. ... 

想了解更多內容,請訪問:

51CTO和華為官方合作共建的鴻蒙技術社區

https://harmonyos.51cto.com

 

責任編輯:jianghua 來源: 鴻蒙社區
相關推薦

2021-07-28 09:40:04

鴻蒙HarmonyOS應用

2021-04-08 14:57:52

鴻蒙HarmonyOS應用

2021-04-20 15:06:42

鴻蒙HarmonyOS應用

2021-07-06 18:21:31

鴻蒙HarmonyOS應用

2021-08-30 17:55:58

鴻蒙HarmonyOS應用

2021-11-17 15:37:43

鴻蒙HarmonyOS應用

2021-03-03 09:42:26

鴻蒙HarmonyOS圖片裁剪

2021-07-20 15:20:40

鴻蒙HarmonyOS應用

2021-04-15 17:47:38

鴻蒙HarmonyOS應用

2021-11-02 14:54:21

鴻蒙HarmonyOS應用

2021-08-10 15:23:08

鴻蒙HarmonyOS應用

2021-10-19 10:04:51

鴻蒙HarmonyOS應用

2021-04-29 14:32:24

鴻蒙HarmonyOS應用

2021-03-10 15:03:40

鴻蒙HarmonyOS應用

2021-06-29 09:28:16

鴻蒙HarmonyOS應用

2021-03-24 09:30:49

鴻蒙HarmonyOS應用

2021-08-03 10:07:41

鴻蒙HarmonyOS應用

2021-08-26 16:07:46

鴻蒙HarmonyOS應用

2021-03-01 14:00:11

鴻蒙HarmonyOS應用

2021-08-05 15:06:30

鴻蒙HarmonyOS應用
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久久久国产精品 | 波多野结衣电影一区 | 亚洲日韩中文字幕一区 | 午夜手机在线视频 | 不卡在线视频 | 亚洲天堂中文字幕 | 亚洲精品一区二三区不卡 | 中文字幕在线视频网站 | 免费一级黄色录像 | 精品国产乱码久久久久久牛牛 | 精品综合久久久 | www.蜜桃av | 一级免费看 | 欧美精品二区 | 国产精品我不卡 | 中文字幕一区二区三区日韩精品 | 久久久久国产精品一区二区 | 欧美日韩高清在线观看 | 亚洲福利在线观看 | 久久久久一区二区三区四区 | 午夜伦4480yy私人影院 | 成人视屏在线观看 | 日韩av成人在线观看 | 亚洲精品1| 久久精品国产一区老色匹 | 国产成人福利在线观看 | 在线国产一区二区三区 | 久久国产精品一区二区三区 | 日韩成人在线播放 | 超碰免费在线观看 | 免费国产一区二区 | 日韩欧美三级 | 99精品一级欧美片免费播放 | 天天拍天天操 | 国产精品综合久久 | av色在线 | 国产精品久久久久久久久久 | 亚洲精品一区二三区不卡 | 一区二区在线免费观看视频 | 中文字幕乱码亚洲精品一区 | 国产精品久久欧美久久一区 |