HarmonyOS图片,HarmonyOS App开发造轮子--自定义圆形图片组件
一、背景
在采用Java配合xml布局編寫鴻蒙app頁面的時(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)圓形圖片的效果,后來發(fā)現(xiàn)不行。于是乎想著能不能通過繼承原有的Image自己來動(dòng)手重新自定義一個(gè)支持圓形的圖片組件。
二、思路:
1、對(duì)比之前自己在其他程序開發(fā)中自定義組件的思路,首先尋找父組件Image和Component相關(guān)的Api,看看是否具備OnDraw方法。
2、了解Canvas相關(guān)Api操作,特別是涉及到位圖的操作。
通過翻閱大量資料,發(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、寫一個(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);
}
}
/**
*?通過資源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);
}
}
5、修改config.json文件,代碼如下{
"app":?{
"bundleName":?"com.xdw.customview",
"vendor":?"xdw",
"version":?{
"code":?1,
"name":?"1.0"
},
"apiVersion":?{
"compatible":?4,
"target":?4,
"releaseType":?"Beta1"
}
},
"deviceConfig":?{},
"module":?{
"package":?"com.xdw.customview",
"deviceType":?[
"phone",
"tv",
"tablet",
"car",
"wearable"
],
"reqPermissions":?[
{
"name":?"ohos.permission.INTERNET"
}
],
"distro":?{
"deliveryWithInstall":?true,
"moduleName":?"roundimage",
"moduleType":?"har"
}
}
}
這樣該模塊就可以導(dǎo)出后續(xù)給其他所有工程引用了,后面還可以編譯之后發(fā)布到gradle上直接通過添加依賴來進(jìn)行使用(這個(gè)是后話),下面我們先通過本地依賴導(dǎo)入的方式來調(diào)用這個(gè)自定義組件模塊吧。
四、其他工程調(diào)用該自定義組件并測試效果
1、再來新建一個(gè)工程,然后將之前的模塊導(dǎo)入到新建的工程中(DevEco暫時(shí)不支持自動(dòng)導(dǎo)入外部模塊的操作,需要手動(dòng)導(dǎo)入操作,請(qǐng)關(guān)注我的另外一篇博客)
2、在gradle中引用導(dǎo)入的模塊的組件,代碼如下:
文章后續(xù)內(nèi)容和相關(guān)附件可以點(diǎn)擊下面的原文鏈接前往學(xué)習(xí)
總結(jié)
以上是生活随笔為你收集整理的HarmonyOS图片,HarmonyOS App开发造轮子--自定义圆形图片组件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java类和方法
- 下一篇: 电子行业订单进度追踪的解决方案