日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
HarmonyOS用Matrix實現(xiàn)各種圖片ScaleType縮放

想了解更多內(nèi)容,請訪問:

目前成都創(chuàng)新互聯(lián)公司已為數(shù)千家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)站空間綿陽服務(wù)器托管、企業(yè)網(wǎng)站設(shè)計、工農(nóng)網(wǎng)站維護等服務(wù),公司將堅持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。

和華為官方合作共建的鴻蒙技術(shù)社區(qū)

https://harmonyos.

本文將從零開始實現(xiàn)一個圖片組件,并展示如何使用 Matrix 實現(xiàn)圖片的各種 ScaleType 縮放效果。

背景知識:

Matrix 內(nèi)部通過維護一個 float[9] 的數(shù)組來構(gòu)成 3x3 矩陣的形式,從底層原理來看,所有的變換方法就是更改數(shù)組中某個或某幾個位置的數(shù)值;

Matrix提供了Translate(平移)、Scale(縮放)、Rotate(旋轉(zhuǎn))、Skew(扭曲)四中變換操作,這四種操作實質(zhì)上是調(diào)用了setValues()方法來設(shè)置矩陣數(shù)組來達到變換效果。除Translate(平移)外,Scale(縮放)、Rotate(旋轉(zhuǎn))、Skew(扭曲)都可以圍繞一個中心點來進行,如果不指定,在默認情況下是圍繞(0, 0)來進行相應(yīng)的變換的。

Matrix提供的四種操作,每一種都有pre、set、post三種形式。原因是矩陣乘法不滿足乘法交換律,因此左乘還是右乘最終的效果都不一樣。我們可以把Matrix變換想象成一個隊列,隊列里面包含了若干個變換操作,隊列中每個操作按照先后順序操作變換目標(biāo)完成變換,pre相當(dāng)于向隊首增加一個操作,post相當(dāng)于向隊尾增加一個操作,set相當(dāng)于清空當(dāng)前隊列重新設(shè)置。

鴻蒙 Image 組件沒有對外公開 setMatrix 接口,如果項目中需要通過 setMatrix 來控制圖片顯示,可參考本文,自己實現(xiàn)自繪式 Image 組件。

創(chuàng)建圖片組件

先創(chuàng)建一個組件類 MyImageComponent,因為是從零開始,所以我們從 Component 繼承,包含以下三個屬性:

 
 
 
 
  1. public class MyImageComponent extends Component implements Component.DrawTask {   
  2.     // 圖片資源,從 src 屬性讀取
  3.     private Element element;
  4.     // 讀取 scaleType 屬性
  5.     private ScaleType scaleType = ScaleType.fitCenter;
  6.     // 用于實現(xiàn) scaleType 的 Matrix 
  7.     private final Matrix matrix = new Matrix();
  8.     
  9.     // ...其他構(gòu)造函數(shù)略
  10.     public MyImageComponent(Context context, AttrSet attrSet, int resId) {
  11.         super(context, attrSet, resId);
  12.         init(attrSet);
  13.     }
  14. }

然后執(zhí)行初始化流程:

 
 
 
 
  1. // 初始化,包括讀取屬性,根據(jù) scaleType 設(shè)置 matrix,添加繪制方法     
  2.    private void init(AttrSet attrSet) {
  3.        readAttrSet(attrSet);      
  4.        dealScaleType();
  5.        addDrawTask(this);
  6.    }
  7.    // 讀取 xml 屬性,包括 src 和 scaleType
  8.    private void readAttrSet(AttrSet attrSet) {
  9.        element = attrSet.getAttr("src").get().getElement();
  10.        
  11.        if (attrSet.getAttr("scaleType").isPresent()) {
  12.            String scaleTypeString = attrSet.getAttr("scaleType").get().getStringValue();
  13.            scaleType = Utils.getEnumFromString(ScaleType.class, scaleTypeString, ScaleType.center);
  14.        }
  15.    }
  16.    // 根據(jù) scaleType 屬性實現(xiàn)對應(yīng)的縮放效果
  17.    private void dealScaleType() {
  18.        switch (scaleType) {
  19.            default:
  20.            case fitCenter:
  21.                fitCenter();
  22.                break;
  23.            case center:
  24.                center();
  25.                break;
  26.            case fitXY:
  27.                fitXY();
  28.                break;
  29.            case fitStart:
  30.                fitStart();
  31.                break;
  32.            case fitEnd:
  33.                fitEnd();
  34.                break;
  35.            case centerCrop:
  36.                centerCrop();
  37.                break;
  38.            case centerInside:
  39.                centerInside();
  40.                break;
  41.        }
  42.    }
  43.    private int getDisplayWidth() {
  44.        return getWidth() - getPaddingLeft() - getPaddingRight();
  45.    }
  46.  
  47.    private int getDisplayHeight() {
  48.        return getHeight() - getPaddingLeft() - getPaddingRight();
  49.    }
  50. private int getElementWidth() {
  51.        return element.getWidth();
  52.    }
  53.    private int getElementHeight() {
  54.        return element.getHeight();
  55.    }

ScaleType 效果展示和對應(yīng)源碼

以下逐個展示各種 ScaleType 效果及其實現(xiàn)代碼,為方便對比不同大小的圖片的 ScaleType 差異,準(zhǔn)備了一大一小兩張圖片。

用于預(yù)覽的 xml 布局代碼如下:

 
 
 
 
  1.     xmlns:ohos="http://schemas.huawei.com/res/ohos"
  2.     xmlns:app="http://schemas.ohos.com/apk/res-auto"
  3.     ohos:height="match_parent"
  4.     ohos:width="match_parent"
  5.     ohos:alignment="center"
  6.     ohos:orientation="vertical">
  7.     
  8.         ohos:width="200vp"
  9.         ohos:height="200vp"
  10.         ohos:background_element="#4682B4"
  11.         ohos:margin="6vp"
  12.         app:src="$media:big"
  13.         app:scaleType="center"
  14.         />
  15.     
  16.         ohos:width="200vp"
  17.         ohos:height="200vp"
  18.         ohos:margin="6vp"
  19.         ohos:background_element="#4682B4"
  20.         app:src="$media:small"
  21.         app:scaleType="center"
  22.         />

以下是各種 scaleType 的效果和源碼:

center

 
 
 
 
  1. /**
  2.     * 圖片居中顯示在組件中,不對圖片進行縮放
  3.     */
  4.    private void center() {
  5.        float wTranslate = (getDisplayWidth() - getElementWidth()) * 0.5f;
  6.        float hTranslate = (getDisplayHeight() - getElementHeight()) * 0.5f;
  7.        matrix.postTranslate(wTranslate, hTranslate);
  8.    }

fitCenter

保持圖片的寬高比,對圖片進行X和Y方向縮放,直到一個方向鋪滿組件,縮放后的圖片居中顯示在組件中。

 
 
 
 
  1. private void fitCenter() {
  2.         float wPercent = (float)getDisplayWidth() / (float)getElementWidth();
  3.         float hPercent = (float)getDisplayHeight() / (float)getElementHeight();
  4.         float minPercent = Math.min(wPercent, hPercent);
  5.         float targetWidth = minPercent * getElementWidth();
  6.         float targetHeight = minPercent * getElementHeight();
  7.         float wTranslate = (getDisplayWidth() - targetWidth) * 0.5f;
  8.         float hTranslate = (getDisplayHeight() - targetHeight) * 0.5f;
  9.         matrix.setScale(minPercent, minPercent);
  10.         matrix.postTranslate(wTranslate, hTranslate);
  11.     }

fitXY

對X和Y方向獨立縮放,直到圖片鋪滿組件。這種方式可能會改變圖片原本的寬高比,導(dǎo)致圖片拉伸變形。

 
 
 
 
  1. private void fitXY(){
  2.        float wPercent = (float)getDisplayWidth() / (float)getElementWidth();
  3.        float hPercent = (float)getDisplayHeight() / (float)getElementHeight();
  4.        matrix.setScale(wPercent, hPercent);
  5.    }

fitStart

保持圖片的寬高比,對圖片進行X和Y方向縮放,直到一個方向鋪滿組件,縮放后的圖片與組件左上角對齊進行顯示。

 
 
 
 
  1. private void fitStart() {
  2.       float wPercent = (float)getDisplayWidth() / (float)getElementWidth();
  3.       float hPercent = (float)getDisplayHeight() / (float)getElementHeight();
  4.       float minPercent = Math.min(wPercent, hPercent);
  5.       
  6.       matrix.setScale(minPercent, minPercent);
  7.   }

fitEnd

保持圖片的寬高比,對圖片進行X和Y方向縮放,直到一個方向鋪滿組件,縮放后的圖片與組件右下角對齊進行顯示。

 
 
 
 
  1. private void fitEnd() {
  2.      float wPercent = (float)getDisplayWidth() / (float)getElementWidth();
  3.      float hPercent = (float)getDisplayHeight() / (float)getElementHeight();
  4.      float minPercent = Math.min(wPercent, hPercent);
  5.      float targetWidth = minPercent * getElementWidth();
  6.      float targetHeight = minPercent * getElementHeight();
  7.      float wTranslate = getDisplayWidth() - targetWidth;
  8.      float hTranslate = getDisplayHeight() - targetHeight;
  9.      matrix.setScale(minPercent, minPercent);
  10.      matrix.postTranslate(wTranslate, hTranslate);
  11.  }

centerCrop

保持圖片的寬高比,等比例對圖片進行X和Y方向縮放,直到每個方向都大于等于組件對應(yīng)的尺寸,縮放后的圖片居中顯示在組件中,超出部分做裁剪處理。

 
 
 
 
  1. private void centerCrop() {
  2.       float scale;
  3.       float dx;
  4.       float dy;
  5.       if (getElementWidth() * getDisplayHeight() > getDisplayWidth() * getElementHeight()) {
  6.           scale = (float)getDisplayHeight() / (float)getElementHeight();
  7.           dx = (getDisplayWidth() - getElementWidth() * scale) * 0.5f;
  8.           dy = 0f;
  9.       } else {
  10.           scale = (float)getDisplayWidth() / (float)getElementWidth();
  11.           dx = 0f;
  12.           dy = (getDisplayHeight() - getElementHeight() * scale) * 0.5f;
  13.       }
  14.       matrix.setScale(scale, scale);
  15.       matrix.postTranslate(dx + 0.5f, dy + 0.5f);
  16.   }

centerInside

如果圖片寬度<= 組件寬度&&圖片高度<= 組件高度,不執(zhí)行縮放,居中顯示在組件中。其余情況按 fitCenter 處理。

 
 
 
 
  1. private void centerInside() {
  2.        if (getElementWidth() <= getDisplayWidth() && getElementHeight() <= getElementHeight()){
  3.            float wTranslate = (getDisplayWidth() - getElementWidth()) * 0.5f;
  4.            float hTranslate = (getDisplayHeight() - getElementHeight()) * 0.5f;            
  5.            matrix.setTranslate(wTranslate, hTranslate);
  6.        } else {
  7.            fitCenter();
  8.        }
  9.    }

繪制圖片組件

關(guān)鍵是這句 canvas.concat(matrix)

 
 
 
 
  1. @Override
  2.     public void onDraw(Component component, Canvas canvas) {
  3.         // 以下是關(guān)鍵代碼,將 matrix 應(yīng)用到 canvas
  4.         canvas.concat(matrix);        
  5.         // 將圖片繪制到 canvas
  6.         element.drawToCanvas(canvas);
  7.     }

項目地址:my-image-component

想了解更多內(nèi)容,請訪問:

和華為官方合作共建的鴻蒙技術(shù)社區(qū)

https://harmonyos.


當(dāng)前標(biāo)題:HarmonyOS用Matrix實現(xiàn)各種圖片ScaleType縮放
當(dāng)前路徑:http://www.5511xx.com/article/dpgojcs.html