鴻蒙HarmonyOS App開(kāi)發(fā)造輪子之自定義圓形圖片組件的實(shí)例代碼
一、背景
在采用Java配合x(chóng)ml布局編寫(xiě)鴻蒙app頁(yè)面的時(shí)候,發(fā)現(xiàn)sdk自帶的Image組件并不能將圖片設(shè)置成圓形,反復(fù)了翻閱了官方API手冊(cè)(主要查閱了Compont和Image相關(guān)的API),起初發(fā)現(xiàn)了一個(gè)setCornerRadius方法,于是想著將圖片寬度和高度設(shè)置為一樣,然后調(diào)用該方法將radios設(shè)置為寬度或者高度的一半,以為可以實(shí)現(xiàn)圓形圖片的效果,后來(lái)發(fā)現(xiàn)不行。于是乎想著能不能通過(guò)繼承原有的Image自己來(lái)動(dòng)手重新自定義一個(gè)支持圓形的圖片組件。
二、思路:
1、對(duì)比之前自己在其他程序開(kāi)發(fā)中自定義組件的思路,首先尋找父組件Image和Component相關(guān)的Api,看看是否具備OnDraw方法。
2、了解Canvas相關(guān)Api操作,特別是涉及到位圖的操作。
通過(guò)翻閱大量資料,發(fā)現(xiàn)了兩個(gè)關(guān)鍵的api,分別是Component的addDrawTask方法和其內(nèi)部靜態(tài)接口DrawTask


三、自定義組件模塊
1、新建一個(gè)工程之后,創(chuàng)建一個(gè)獨(dú)立的Java FA模塊,然后刪除掉里面所有布局以及自動(dòng)生成的java代碼,然后自己創(chuàng)建一個(gè)class繼承ImageView
2、寫(xiě)一個(gè)類繼承ImageView,在其中暴露出public的設(shè)置圓形圖片的api方法以供后面調(diào)用;
3、在原有的Image組件獲取到位圖之后,利用該位圖數(shù)據(jù)利用addDrawTask方法配合Canvas進(jìn)行位圖輸出形狀的重新繪制,這里需要使用Canvas的一個(gè)
關(guān)鍵api方法drawPixelMapHolderRoundRectShape;
4、注意,為了讓Canvas最后輸出的圖片為圓形,需要將圖片在布局中的寬度和高度設(shè)置成一樣,否則輸出的為圓角矩形或者橢圓形。
最后封裝后的詳細(xì)代碼如下:
package com.xdw.customview;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Image;
import ohos.agp.render.PixelMapHolder;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Rect;
import ohos.media.image.common.Size;
import java.io.InputStream;
/**
* Created by 夏德旺 on 2021/1/1 11:00
*/
public class RoundImage extends Image {
private static final HiLogLabel LABEL = new HiLogLabel(HiLog.DEBUG, 0, "RoundImage");
private PixelMapHolder pixelMapHolder;//像素圖片持有者
private RectFloat rectDst;//目標(biāo)區(qū)域
private RectFloat rectSrc;//源區(qū)域
public RoundImage(Context context) {
this(context,null);
}
public RoundImage(Context context, AttrSet attrSet) {
this(context,attrSet,null);
}
/**
* 加載包含該控件的xml布局,會(huì)執(zhí)行該構(gòu)造函數(shù)
* @param context
* @param attrSet
* @param styleName
*/
public RoundImage(Context context, AttrSet attrSet, String styleName) {
super(context, attrSet, styleName);
HiLog.error(LABEL,"RoundImage");
}
public void onRoundRectDraw(int radius){
//添加繪制任務(wù)
this.addDrawTask((view, canvas) -> {
if (pixelMapHolder == null){
return;
}
synchronized (pixelMapHolder) {
//給目標(biāo)區(qū)域賦值,寬度和高度取自xml配置文件中的屬性
rectDst = new RectFloat(0,0,getWidth(),getHeight());
//繪制圓角圖片
canvas.drawPixelMapHolderRoundRectShape(pixelMapHolder, rectSrc, rectDst, radius, radius);
pixelMapHolder = null;
}
});
}
//使用canvas繪制圓形
private void onCircleDraw(){
//添加繪制任務(wù),自定義組件的核心api調(diào)用,該接口的參數(shù)為Component下的DrawTask接口
this.addDrawTask((view, canvas) -> {
if (pixelMapHolder == null){
return;
}
synchronized (pixelMapHolder) {
//給目標(biāo)區(qū)域賦值,寬度和高度取自xml配置文件中的屬性
rectDst = new RectFloat(0,0,getWidth(),getHeight());
//使用canvas繪制輸出圓角矩形的位圖,該方法第4個(gè)參數(shù)和第5個(gè)參數(shù)為radios參數(shù),
// 繪制圖片,必須把圖片的寬度和高度先設(shè)置成一樣,然后把它們?cè)O(shè)置為圖片寬度或者高度一半時(shí)則繪制的為圓形
canvas.drawPixelMapHolderRoundRectShape(pixelMapHolder, rectSrc, rectDst, getWidth()/2, getHeight()/2);
pixelMapHolder = null;
}
});
}
/**
*獲取原有Image中的位圖資源后重新檢驗(yàn)繪制該組件
* @param pixelMap
*/
private void putPixelMap(PixelMap pixelMap){
if (pixelMap != null) {
rectSrc = new RectFloat(0, 0, pixelMap.getImageInfo().size.width, pixelMap.getImageInfo().size.height);
pixelMapHolder = new PixelMapHolder(pixelMap);
invalidate();//重新檢驗(yàn)該組件
}else{
pixelMapHolder = null;
setPixelMap(null);
}
}
/**
* 通過(guò)資源ID獲取位圖對(duì)象
**/
private PixelMap getPixelMap(int resId) {
InputStream drawableInputStream = null;
try {
drawableInputStream = getResourceManager().getResource(resId);
ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
sourceOptions.formatHint = "image/png";
ImageSource imageSource = ImageSource.create(drawableInputStream, null);
ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
decodingOptions.desiredSize = new Size(0, 0);
decodingOptions.desiredRegion = new Rect(0, 0, 0, 0);
decodingOptions.desiredPixelFormat = PixelFormat.ARGB_8888;
PixelMap pixelMap = imageSource.createPixelmap(decodingOptions);
return pixelMap;
} catch (Exception e) {
e.printStackTrace();
} finally {
try{
if (drawableInputStream != null){
drawableInputStream.close();
}
}catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
/**
* 對(duì)外調(diào)用的api,設(shè)置圓形圖片方法
* @param resId
*/
public void setPixelMapAndCircle(int resId){
PixelMap pixelMap = getPixelMap(resId);
putPixelMap(pixelMap);
onCircleDraw();
}
/**
* 對(duì)外調(diào)用的api,設(shè)置圓角圖片方法
* @param resId
* @param radius
*/
public void setPixelMapAndRoundRect(int resId,int radius){
PixelMap pixelMap = getPixelMap(resId);
putPixelMap(pixelMap);
onRoundRectDraw(radius);
}
}
到此這篇關(guān)于鴻蒙HarmonyOS App開(kāi)發(fā)造輪子之自定義圓形圖片組件的文章就介紹到這了,更多相關(guān)鴻蒙HarmonyOS自定義圓形圖片組件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- HarmonyOS中使用Node-API開(kāi)發(fā)的典型場(chǎng)景示例
- HarmonyOS系統(tǒng)利用AVPlayer開(kāi)發(fā)視頻播放功能
- 鴻蒙中@State的原理使用詳解(HarmonyOS 5)
- HarmonyOS Next音樂(lè)播放器項(xiàng)目實(shí)現(xiàn)代碼
- 鴻蒙HarmonyOS開(kāi)發(fā):Navigation路由導(dǎo)航功能和實(shí)踐
- 鴻蒙(HarmonyOS)實(shí)現(xiàn)隱私政策彈窗效果
- 鴻蒙開(kāi)發(fā)之處理圖片位圖操作的方法詳解(HarmonyOS鴻蒙開(kāi)發(fā)基礎(chǔ)知識(shí))
- 鴻蒙HarmonyOS中的ArkUI組件庫(kù)特性與常用組件實(shí)例演示
相關(guān)文章
SpringMVC中的ConversionServiceExposingInterceptor工具類解析
這篇文章主要介紹了SpringMVC中的ConversionServiceExposingInterceptor工具類解析,ConversionServiceExposingInterceptor是Spring MVC的一個(gè)HandlerInterceptor,用于向請(qǐng)求添加一個(gè)屬性,需要的朋友可以參考下2023-12-12
spring boot使用thymeleaf為模板的基本步驟介紹
Spring Boot項(xiàng)目的默認(rèn)模板引擎是Thymeleaf,這沒(méi)什么好說(shuō)的,個(gè)人覺(jué)得也非常好,下面這篇文章主要給大家介紹了關(guān)于spring boot使用thymeleaf為模板的相關(guān)資料,需要的朋友可以參考借鑒,下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-01-01
Springboot實(shí)現(xiàn)導(dǎo)入導(dǎo)出Excel的方法
今天帶各位小伙伴學(xué)習(xí)Springboot實(shí)現(xiàn)導(dǎo)入導(dǎo)出Excel的方法,文中有非常詳細(xì)的介紹,對(duì)正在學(xué)習(xí)java的小伙伴們有很好地幫助,需要的朋友可以參考下2021-05-05
Java反轉(zhuǎn)數(shù)組輸出實(shí)例代碼
這篇文章主要給大家介紹了關(guān)于Java反轉(zhuǎn)數(shù)組輸出以及利用Java實(shí)現(xiàn)字符串逆序輸出的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
麒麟系統(tǒng)環(huán)境搭建之JDK的安裝圖文教程
麒麟系統(tǒng)是國(guó)產(chǎn)操作系統(tǒng),而java JDK是java編程語(yǔ)言的運(yùn)行環(huán)境,這篇文章主要介紹了麒麟系統(tǒng)環(huán)境搭建之JDK安裝圖文教程的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2026-01-01
Java集合Map常見(jiàn)問(wèn)題_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要為大家詳細(xì)整理了Java集合Map常見(jiàn)問(wèn)題,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05
jmeter+ant+jenkins自動(dòng)化測(cè)試環(huán)境配置搭建過(guò)程
在搭建jmeter+ant+jenkins環(huán)境有些前提條件,那就是要先配置好java環(huán)境、安裝好jenkins以及配置好jmeter,這樣才能省去很多的事情,對(duì)jmeter+ant+jenkins自動(dòng)化測(cè)試環(huán)境配置搭建過(guò)程感興趣的朋友一起看看吧2021-12-12
java實(shí)現(xiàn)數(shù)據(jù)庫(kù)主鍵生成示例
這篇文章主要介紹了java實(shí)現(xiàn)數(shù)據(jù)庫(kù)主鍵生成示例,需要的朋友可以參考下2014-03-03

