基于安卓平台的圖檔裁切元件crop_image_layout(https://github.com/yulu/crop-image-layout ),實作了鴻蒙化遷移和重構,代碼已經開源到(https://gitee.com/isrc_ohos/crop_image_layout_ohos ),目前已經獲得了很多人的star和fork ,歡迎各位下載下傳使用并提出寶貴意見!
crop_image_layout_ohos元件能對圖檔進行旋轉和自定義裁切的操作,并且無論待裁切圖檔原尺寸有多大或多小,最終都将在以最佳尺寸在元件内顯示。同時,該元件操作界面簡潔且使用方法簡單,易被開發者使用或優化,能夠提升應用的豐富性和可操作性。
元件中可以通過操作圖檔、裁切框、按鈕,最終實作在圖檔中裁切部分區域并進行顯示的效果,元件的運作效果如圖1所示。
::: hljs-center
圖1 crop_image_layout_ohos元件的運作效果圖
:::
對應運作效果圖,詳細解釋其主要提供的功能:
點選“rotate”按鈕可以對圖檔進行旋轉操作。
手指按住裁切框内任意處并拖動,可實作裁切框移動,裁切框停止移動時,框内的圖檔即為想要裁切的圖檔;
被選中區域的左上角和右下角坐标會在圖檔下方的文本框中進行顯示;
點選“crop”按鈕可對選中的圖檔區域進行裁切,之後會跳轉到第二個界面顯示裁切後的圖檔;
1.元件的整體使用流程
圖2 元件使用流程示意圖
在介紹元件的使用前,先來介紹下構成crop_image_layout_ohos元件功能的3個重要部分:
-裁切框:負責劃定圖檔的裁切區域;
-裁切圖檔:是指被導入元件中,即将被裁切的圖檔;
-元件區域:是指元件所在的位置;
元件的使用過程可以概括為首先設定裁切框的位置(坐标),然後将裁切框坐标資料添加到裁切圖檔中,最後将裁切框和裁切圖檔添加到元件區域中。
在這過程中,元件還實作了對裁切圖檔和裁切框尺寸的适配顯示效果,這部分的具體原理會在library解析部分進行講解。
2.元件的具體使用步驟
下面介紹crop_image_layout_ohos元件的具體使用方法,共分為6個步驟:
步驟1. 在xml檔案中添加editphotoview控件。
步驟2. 導入所需類并執行個體化類對象。
步驟3. 将裁切框坐标資料設定到裁切圖檔。
步驟4. 将裁切圖檔和裁切框添加到布局中
步驟5. 顯示裁切框左上角和右下角坐标值。
步驟6. 設定監聽事件。
(1)在xml檔案中添加editphotoview控件
在xml檔案中以com.huawei.croplayout.editphotoview為控件名添加editphotoview控件,用來顯示crop_image_layout_ohos的元件區域。并分别設定裁切框拐角和邊的顔色以及裁切圖檔未被選中部分的陰影顔色,如圖所示。
圖3 屬性設定示意圖
(2)導入所需類并執行個體化類對象
在mainabilityslice類的onstart()方法中,分别導入類onboxchangedlisteneron、editphotoview、edittableimage、scalablebox。
boxchangedlistener類用于監聽裁切框變化;
editphotoview類用于設定元件區域;
edittableimage類用于設定裁切圖檔;
scalablebox類用于設定裁切框;
建立editphotoview類和text類對象分别用于綁定crop_image_layout_ohos的元件區域和用于顯示裁切框坐标的文本控件;執行個體化edittableimage類對象image,使其包含圖1所示的裁切圖檔,實作元件裁切圖檔的導入。建立一個元素類型為scalablebox的list,并将其命名為boxes,用于盛納裁切框的坐标。新執行個體化一個左上角坐标為(25,180)、右下角坐标為(640,880)的裁切框對象,并調用add()方法将其添加到上述boxes中。
(3)将裁切框坐标資料設定到裁切圖檔
通過setboxes()方法将boxes中裁切框對象的坐标資料設定到裁切圖檔image中,實作裁切框相對裁切圖檔的位置設定;
(4)将裁切圖檔和裁切框添加到布局中
調用intview()方法,建立裁切圖檔和裁切框的視圖,并将其添加到元件布局中進行顯示。
(5)顯示裁切框左上角和右下角坐标值
重新聲明一個scalablebox類型的對象activebox,用于動态取裁切框的坐标,并将其通過text在界面上顯示出來。
(6)設定監聽事件
元件區域監聽事件
為元件區域對象imageview設定監聽事件,當裁切框位置發生變化時,将其坐标設定到text對象boxtext中進行顯示。
旋轉按鈕“rotate”監聽事件
聲明一個button類對象rotatebutton将其與“rotate_button”控件綁定。為其設定點選監聽事件,按鈕被點選時,通過元件區域對象imageview調用rotateimageview()方法實作裁切圖檔向右旋轉90°的效果。
裁切按鈕“crop”監聽事件
聲明一個button類對象cropbutton将其與“crop_button”控件綁定,并設定點選監聽事件。按鈕被點選時,通過裁切圖檔image調用croporiginalimage()方法得到裁切後的圖檔并将其存放于pixelmap類對象中;通過intent跳轉到第二個界面,并将裁切後的圖檔作為參數傳入,顯示在第二個界面中。
library部分将圍繞圖2,對crop_image_layout_ohos元件的原理和執行邏輯進行梳理。其中會涉及到scalablebox類、edittableimage類、editphotoview類、selectionview類、和imagehelper類;
scalablebox類、edittableimage類、editphotoview類在上一節中簡單介紹過是用來設定元件區域、裁切圖檔和裁切框的;
selectionview類用于用于設定裁剪框所在的視圖;
imagehelper類相當于一個圖檔操作輔助工具,用來完成從原裁剪圖檔中擷取pixelmap和旋轉圖檔等圖檔處理操作。
1.設定裁切框(執行個體化其尺寸)
圖4 裁切框坐标示意圖
在sample解析中我們講過,需要調用add()方法将新執行個體化的左上角坐标為(25,180)、右下角坐标為(640,880)的裁切框加入到boxes對象中。其中,左上角坐标對應圖4中的(x1,y1),右上角對應圖4中的(x2,y2),通過設定裁切框對角線上兩個點,就可以唯一确定其大小和位置了。
執行個體化過程需要通過scalablebox類的構造函數,設定裁切框左上角和右下角的坐标。
2.将裁切框坐标資料設定到裁切圖檔
擷取裁切框清單boxes的第一個對象,即我們之前設定好對角線坐标的裁切框資料,并将其添加到裁切圖檔中。這是通過editableimage類的setboxes()方法實作的。
在該方法中,若裁切框對象清單boxes不為空且尺寸大于0,則将boxes賦給editableimage類的成員變量originalboxes,用于存儲所有的裁剪框對象的資料;将另一個此類的成員變量copyofactivebox執行個體化,用于存儲被選中的裁剪框兩個角的坐标值;其中,activeboxidx是指在boxes中盛納裁切框坐标的下标,list可以為使用者預留多個裁切框坐标,本元件中隻是用下表為0的裁切框坐标。
3.将裁切圖檔和裁剪框添加到布局中
該功能是通過editphotoview類的initview()方法實作的。先根據建立editphotoview對象時傳入的裁切框尺寸、邊角尺寸和顔色等屬性,将selectionview類執行個體化,用于展示裁剪框的視圖;然後根據傳入的裁切圖檔執行個體化得到image圖檔類對象,用于展示裁切圖檔的視圖;再将selectionview類對象和image對象的布局設定為跟随父元件,并将兩者添加到裁切元件區域布局中,實作裁切框和裁切圖檔的顯示。
分别通過setviewsize()方法設定裁切圖檔視圖區域尺寸、setpixelmap()為其設定裁切圖檔位圖格式、setscalemode()方法為其設定圖檔縮放模式為中心縮放、setboxsize()方法設定裁切圖檔和裁切框适配後的尺寸。
(1)在裁切圖檔視圖區域中适配裁切圖檔
由于裁切圖檔的視圖區域與元件區域的大小相同,二裁切圖檔的大小是不固定的,是以裁切圖檔在顯示到其視圖區域時,需進行尺寸的适配。
上述功能是由editableimage類的getfitsize()方法提供,該方法在上述setboxsize()方法中被調用。通過該方法能夠将裁切圖檔與其視圖區域進行适配,同時傳回适配後圖檔尺寸。這是為了更好地在裁切圖檔視圖區域中展示圖檔,無論過大或過小尺寸的圖檔都能在此區域中被縮放至最合适的程度顯示。原理可參考圖5。
圖5 适配圖檔尺寸原理圖(左:ratio>viewratio,右反之)
先計算原裁切圖檔(即粉色矩形)寬和高的比值ratio(即a/b)群組件區域(即黃色矩形)寬和高的比值viewratio(即c/d)。
判斷若原裁切圖檔寬高比大于裁切圖檔視圖區域寬高比即圖5中左圖的情況,則說明可以将原裁切圖檔最大程度放大至寬a與裁切圖檔視圖區域寬c長度一緻的尺寸(即藍色矩形),此時原裁切圖檔高b按ratio放大後的長度一定小于裁切圖檔視圖區域高d,是以可以根據圖檔寬放大的倍數factor求出放大後高的長度。
若原裁切圖檔寬高比小于裁切圖檔視圖區域寬高比即圖5中右圖的情況,與上一種情況同理,則說明可以将原裁切圖檔最大程度放大至高b與裁切圖檔視圖區域高d長度一緻的尺寸(即藍色矩形),此時原裁切圖檔寬a按ratio放大後的長度一定小于裁切圖檔視圖區域寬c,是以可以根據圖檔高放大的倍數factor求出放大後寬的長度。
計算完成後将圖檔放大後的寬和高分别存放在int型數組fitsize[]中。上述是以原裁切圖檔尺寸小于裁切圖檔視圖區域為例,反之同理。
(2)将裁切框和圖檔進行适配
裁切框需要與裁切圖檔保持相同的顯示比例,是以裁切框需要和裁切圖檔進行适配。
上述功能是由selectionview類的setboxsize()方法。擷取适配後圖檔的寬高,與裁切框寬高進行計算得到originx和originy,并調用setdisplayboxes()方法設定适配後裁切框的坐标。
setdisplayboxes()方法中核心部分是根據圖檔縮放比例計算适配後裁切框對角線上兩點的坐标。先計算圖檔縮放前後寬的比值scale(即c/a),用之前執行個體化時設定的裁切框初始尺寸的左上角橫坐标x1與縮放比例scale相乘得到适配後的橫坐标,再加上前面計算好的originx,即得到适配後的裁切框左上角橫坐标scalex1,右下角橫坐标scalex2、左上角豎坐标scaley1、右下角豎坐标scaley2同理。
王時予 李珂 朱偉 鄭森文 陳美汝
【本文正在參與51cto harmonyos技術社群創作者激勵-星光計劃1.0】
https://harmonyos.51cto.com/posts/8719
想了解更多關于鴻蒙的内容,請通路:
51cto和華為官方戰略合作共建的鴻蒙技術社群
https://harmonyos.51cto.com/#bkwz