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

HarmonyOS用Matrix實(shí)現(xiàn)各種圖片ScaleType縮放

開(kāi)發(fā) 前端 OpenHarmony
本文將從零開(kāi)始實(shí)現(xiàn)一個(gè)圖片組件,并展示如何使用 Matrix 實(shí)現(xiàn)圖片的各種 ScaleType 縮放效果,鴻蒙 Image 組件沒(méi)有對(duì)外公開(kāi) setMatrix 接口,可參考本文,自己實(shí)現(xiàn)自繪式 Image 組件。

[[418482]]

想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):

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

https://harmonyos.51cto.com

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

背景知識(shí):

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

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

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

鴻蒙 Image 組件沒(méi)有對(duì)外公開(kāi) setMatrix 接口,如果項(xiàng)目中需要通過(guò) setMatrix 來(lái)控制圖片顯示,可參考本文,自己實(shí)現(xiàn)自繪式 Image 組件。

創(chuàng)建圖片組件

先創(chuàng)建一個(gè)組件類(lèi) MyImageComponent,因?yàn)槭菑牧汩_(kāi)始,所以我們從 Component 繼承,包含以下三個(gè)屬性:

  1. public class MyImageComponent extends Component implements Component.DrawTask {    
  2.     // 圖片資源,從 src 屬性讀取 
  3.     private Element element; 
  4.     // 讀取 scaleType 屬性 
  5.     private ScaleType scaleType = ScaleType.fitCenter; 
  6.     // 用于實(shí)現(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.     } 

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

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

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

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

【中軟國(guó)際】HarmonyOS 用 Matrix 實(shí)現(xiàn)各種圖片 ScaleType 縮放-鴻蒙HarmonyOS技術(shù)社區(qū)
【中軟國(guó)際】HarmonyOS 用 Matrix 實(shí)現(xiàn)各種圖片 ScaleType 縮放-鴻蒙HarmonyOS技術(shù)社區(qū)

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

  1. <?xml version="1.0" encoding="utf-8"?> 
  2. <DirectionalLayout 
  3.     xmlns:ohos="http://schemas.huawei.com/res/ohos" 
  4.     xmlns:app="http://schemas.ohos.com/apk/res-auto" 
  5.     ohos:height="match_parent" 
  6.     ohos:width="match_parent" 
  7.     ohos:alignment="center" 
  8.     ohos:orientation="vertical"
  9.  
  10.     <com.bm.mycomponent.MyImageComponent 
  11.         ohos:width="200vp" 
  12.         ohos:height="200vp" 
  13.         ohos:background_element="#4682B4" 
  14.         ohos:margin="6vp" 
  15.         app:src="$media:big" 
  16.         app:scaleType="center" 
  17.         /> 
  18.     <com.bm.mycomponent.MyImageComponent 
  19.         ohos:width="200vp" 
  20.         ohos:height="200vp" 
  21.         ohos:margin="6vp" 
  22.         ohos:background_element="#4682B4" 
  23.         app:src="$media:small" 
  24.         app:scaleType="center" 
  25.         /> 
  26.  
  27. </DirectionalLayout> 

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

center

【中軟國(guó)際】HarmonyOS 用 Matrix 實(shí)現(xiàn)各種圖片 ScaleType 縮放-鴻蒙HarmonyOS技術(shù)社區(qū)
  1. /** 
  2.     * 圖片居中顯示在組件中,不對(duì)圖片進(jìn)行縮放 
  3.     */ 
  4.    private void center() { 
  5.        float wTranslate = (getDisplayWidth() - getElementWidth()) * 0.5f; 
  6.        float hTranslate = (getDisplayHeight() - getElementHeight()) * 0.5f; 
  7.  
  8.        matrix.postTranslate(wTranslate, hTranslate); 
  9.    } 

fitCenter

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

【中軟國(guó)際】HarmonyOS 用 Matrix 實(shí)現(xiàn)各種圖片 ScaleType 縮放-鴻蒙HarmonyOS技術(shù)社區(qū)
  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.  
  6.         float targetWidth = minPercent * getElementWidth(); 
  7.         float targetHeight = minPercent * getElementHeight(); 
  8.  
  9.         float wTranslate = (getDisplayWidth() - targetWidth) * 0.5f; 
  10.         float hTranslate = (getDisplayHeight() - targetHeight) * 0.5f; 
  11.  
  12.         matrix.setScale(minPercent, minPercent); 
  13.         matrix.postTranslate(wTranslate, hTranslate); 
  14.     } 

fitXY

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

【中軟國(guó)際】HarmonyOS 用 Matrix 實(shí)現(xiàn)各種圖片 ScaleType 縮放-鴻蒙HarmonyOS技術(shù)社區(qū)
  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

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

【中軟國(guó)際】HarmonyOS 用 Matrix 實(shí)現(xiàn)各種圖片 ScaleType 縮放-鴻蒙HarmonyOS技術(shù)社區(qū)
  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

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

【中軟國(guó)際】HarmonyOS 用 Matrix 實(shí)現(xiàn)各種圖片 ScaleType 縮放-鴻蒙HarmonyOS技術(shù)社區(qū)
  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.  
  6.      float targetWidth = minPercent * getElementWidth(); 
  7.      float targetHeight = minPercent * getElementHeight(); 
  8.      float wTranslate = getDisplayWidth() - targetWidth; 
  9.      float hTranslate = getDisplayHeight() - targetHeight; 
  10.  
  11.      matrix.setScale(minPercent, minPercent); 
  12.      matrix.postTranslate(wTranslate, hTranslate); 
  13.  } 

centerCrop

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

【中軟國(guó)際】HarmonyOS 用 Matrix 實(shí)現(xiàn)各種圖片 ScaleType 縮放-鴻蒙HarmonyOS技術(shù)社區(qū)
  1. private void centerCrop() { 
  2.       float scale; 
  3.       float dx; 
  4.       float dy; 
  5.  
  6.       if (getElementWidth() * getDisplayHeight() > getDisplayWidth() * getElementHeight()) { 
  7.           scale = (float)getDisplayHeight() / (float)getElementHeight(); 
  8.           dx = (getDisplayWidth() - getElementWidth() * scale) * 0.5f; 
  9.           dy = 0f; 
  10.       } else { 
  11.           scale = (float)getDisplayWidth() / (float)getElementWidth(); 
  12.           dx = 0f; 
  13.           dy = (getDisplayHeight() - getElementHeight() * scale) * 0.5f; 
  14.       } 
  15.  
  16.       matrix.setScale(scale, scale); 
  17.       matrix.postTranslate(dx + 0.5f, dy + 0.5f); 
  18.   } 

centerInside

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

【中軟國(guó)際】HarmonyOS 用 Matrix 實(shí)現(xiàn)各種圖片 ScaleType 縮放-鴻蒙HarmonyOS技術(shù)社區(qū)
  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.     } 

項(xiàng)目地址:my-image-component

想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):

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

https://harmonyos.51cto.com

 

責(zé)任編輯:jianghua 來(lái)源: 鴻蒙社區(qū)
相關(guān)推薦

2023-05-11 07:38:51

2012-05-23 15:45:13

JavaScript

2011-09-01 10:20:18

VMworld虛擬化惠普

2011-05-12 11:28:20

按比例縮放

2013-05-27 09:52:35

Android開(kāi)發(fā)移動(dòng)開(kāi)發(fā)移動(dòng)應(yīng)用

2013-05-27 10:01:06

Android開(kāi)發(fā)Android應(yīng)用縮放圖片

2023-09-08 09:12:57

內(nèi)存緩存圖像

2009-12-21 14:31:39

Fedora core

2025-06-04 08:40:00

Go語(yǔ)言鏈表

2023-10-27 08:53:13

Python驗(yàn)證碼圖片識(shí)別

2023-10-19 10:12:34

圖形編輯器開(kāi)發(fā)縮放圖形

2023-09-28 16:15:01

Element XMatrix 2.0

2009-05-08 09:17:48

動(dòng)態(tài)數(shù)據(jù)庫(kù)圖片

2021-08-25 09:38:16

鴻蒙HarmonyOS應(yīng)用

2017-04-27 21:00:33

Android滑動(dòng)分析

2010-06-21 17:08:10

Java框架ScalaSpring

2025-01-02 11:01:13

Apache文件類(lèi)型部署

2014-12-31 16:48:43

Touch touchevent多點(diǎn)觸摸

2015-06-25 09:42:47

swift蘋(píng)果開(kāi)源

2021-08-30 10:16:19

代碼開(kāi)發(fā)文本
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 在线国产一区 | 成人免费在线播放 | 九九热精品视频 | 亚洲欧洲在线视频 | 久久久国产精品 | 国产精品大片 | 国产精品96久久久久久 | 91精品国产综合久久久久 | 日韩av在线一区 | 五月网婷婷 | 久久国产精品99久久久久久丝袜 | 日韩在线播放视频 | 日本久久精品视频 | 欧美日韩久久久 | 逼逼网 | 成人在线免费视频观看 | 黄色欧美在线 | av影音 | 四虎影音 | www.9191| 欧美日韩久久久久 | 国产一区二区三区亚洲 | 国产精品久久久久久久久久免费看 | 久久三区 | 草b视频| 一级一片在线观看 | 麻豆av免费观看 | 国产一区二区三区四区在线观看 | 一级片子 | 色播av| 狠狠操狠狠操 | 日韩一区精品 | 亚洲精品乱码 | 亚洲国产成人在线 | 日日操日日舔 | 日本又色又爽又黄又高潮 | 99精品国产一区二区三区 | 精品国产乱码久久久久久a丨 | 亚洲精品欧美一区二区三区 | 91精品久久久久久久 | 日韩国产精品一区二区三区 |