新聞中心
[[358401]]

創(chuàng)新互聯(lián)公司堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:網(wǎng)站設(shè)計(jì)制作、網(wǎng)站設(shè)計(jì)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時代的治多網(wǎng)站設(shè)計(jì)、移動媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
想了解更多內(nèi)容,請?jiān)L問:
和華為官方合作共建的鴻蒙技術(shù)社區(qū)
https://harmonyos./#zz
前言:
今天是鴻蒙的手機(jī)beta發(fā)布活動,很榮幸受邀來到現(xiàn)場,一會兒可以給大家上個靚照~。
[[358402]]
本篇旨在通過實(shí)踐一些樣例,讓開發(fā)者們快速提高腎上腺素,歡樂的加入鴻蒙應(yīng)用開發(fā)之旅。整篇就是一個完整的實(shí)操樣例,我也盡量在一片中把內(nèi)容都講清楚。
基礎(chǔ)的一些知識點(diǎn),可以訪問我另一個系列:《鴻蒙OS應(yīng)用開發(fā)實(shí)踐》
正文
(一)創(chuàng)建項(xiàng)目
1.創(chuàng)建一個新的TV項(xiàng)目:
2.創(chuàng)建一個新的Java類:
命名為Draw:
這個作為我們的繪畫的核心組件,所以我們讓他繼承Component,方便后面的調(diào)用。需要注意的是,這里導(dǎo)入包名的時候,我們選擇第一個:ohos.agp.components包。
完成后,依然會報錯,提示我們需要創(chuàng)建構(gòu)造函數(shù):
同樣默認(rèn)會有很多構(gòu)造方法,我們選擇第一個(單個參數(shù))即可。
(二)實(shí)現(xiàn)繪畫工具
這樣一個基礎(chǔ)的組件類就創(chuàng)建好了,接著我們構(gòu)思下一畫板工具里需要哪些元素:
畫筆:用于畫出各種點(diǎn)和線。
畫板:用于展現(xiàn)我們到底花了什么,它是內(nèi)容的載體。
所以,根據(jù)以上這些元素,在接下來我們需要在代碼里定義和創(chuàng)建一些內(nèi)容:
- Path mPath = new Path();
- Paint mPaint;
- Point mPrePoint = new Point();
- Point mPreCtrlPoint = new Point();
- Canvas : 畫布的意思,屬于渲染組件,一般用于渲染各種界面元素,這里需要 import ohos.agp.render.Canvas;包
- Path : 路徑的意思,也屬于渲染組件,用于描述繪制的路徑。需要import ohos.agp.render.Path;
- Paint : 表示繪制,屬于渲染組件,用于一些繪制操作,需要import ohos.agp.render.Paint;
- Point : 表示一個點(diǎn),通常由二維坐標(biāo)(x,y)組成,需要import ohos.agp.utils.Point;
所以上面的代碼,我們先定義了一些等待使用的工具變量。
現(xiàn)在我們?nèi)鄙倭艘粋€東西,那就是如何交互?一般的,繪圖這樣的,我們要么鼠標(biāo),要么觸屏,要么就是電子繪筆等。這里我們使用鴻蒙觸摸組件來實(shí)現(xiàn)。
在代碼中去實(shí)現(xiàn)Component.TouchEventListener方法:
實(shí)現(xiàn)onTouchEvent()方法:
onTouchEvent包含兩個參數(shù):Component表示當(dāng)前接收的組件,TouchEvent表示當(dāng)前的觸摸事件。
通過getAction實(shí)例方法可以獲取TouchEvent的狀態(tài):
- TouchEvent.PRIMARY_POINT_DOWN : 按下狀態(tài)
- TouchEvent.PRIMARY_POINT_UP :點(diǎn)按狀態(tài)抬起
- TouchEvent.POINT_MOVE: 點(diǎn)按拖動
我們需要在按下的時候開始記錄點(diǎn)的位置,拖動的時候記錄下整個軌跡,而抬起的時候則不做任何事情。
所以,在onTouchEvent事件函數(shù)中,我們的代碼這樣寫:
- switch (touchEvent.getAction()) {
- case TouchEvent.PRIMARY_POINT_DOWN: {
- MmiPoint point = touchEvent.getPointerPosition(touchEvent.getIndex());
- mPath.moveTo(point.getX(), point.getY());
- mPrePoint.position[0] = point.getX();
- mPrePoint.position[1] = point.getY();
- mPreCtrlPoint.position[0] = point.getX();
- mPreCtrlPoint.position[1] = point.getY();
- return true;
- }
- case TouchEvent.PRIMARY_POINT_UP:
- break;
- case TouchEvent.POINT_MOVE: {
- break;
- }
MmiPoint :表示是人機(jī)交互接口的一個Point,這里用來接收點(diǎn)擊事件的點(diǎn),需要import ohos.multimodalinput.event.MmiPoint;
然后在點(diǎn)擊下去的這一下,指定路徑mPath的moveTo目標(biāo)為當(dāng)前事件點(diǎn)擊獲得的點(diǎn)。
同時也設(shè)置了兩個預(yù)制緩存點(diǎn)的坐標(biāo)為當(dāng)前點(diǎn)擊的點(diǎn)。
抬起的操作,我們這里暫時不做處理。
直接來處理下移動分支下的操作:
- case TouchEvent.POINT_MOVE: {
- MmiPoint point = touchEvent.getPointerPosition(touchEvent.getIndex());
- Point currCtrlPoint = new Point((point.getX() + mPrePoint.position[0]) / 2,
- (point.getY() + mPrePoint.position[1]) / 2);
- mPath.cubicTo(mPrePoint, mPreCtrlPoint, currCtrlPoint);
- mPreCtrlPoint.position[0] = currCtrlPoint.position[0];
- mPreCtrlPoint.position[1] = currCtrlPoint.position[1];
- mPrePoint.position[0] = point.getX();
- mPrePoint.position[1] = point.getY();
- invalidate();
- break;
> 解析:
同樣用MmiPoint來接收點(diǎn)擊輸入,然后先說下mPath.cubicTo:使用path的cubicTo方法來實(shí)現(xiàn)三次貝塞爾曲線,就是說兩個點(diǎn)之間的線有兩個控制點(diǎn)。這樣可以讓曲線更加的平滑,它需要輸入三個點(diǎn)的參數(shù),所以,我們之前定義了兩個Point變量,這里就需要用上了,整體上的原理就是,先把點(diǎn)擊獲得第一個點(diǎn)傳入到曲線函數(shù)中,然后計(jì)算當(dāng)前點(diǎn)擊的位置加上第一個點(diǎn)的二分之一偏移量來細(xì)化得到一個更小的值來作為第三個參數(shù),而第二個參數(shù),我們讓緩存的另一個點(diǎn)直接接收當(dāng)前點(diǎn)擊的點(diǎn)的值,然后傳入到第二個參數(shù)中,最后又更新當(dāng)前位置給第一個點(diǎn),這樣第一個點(diǎn)傳入(舊的點(diǎn)),加上拖動后的當(dāng)前點(diǎn)(新點(diǎn)),在當(dāng)前點(diǎn)的二分偏移量的點(diǎn),構(gòu)成了三點(diǎn)傳給了曲線函數(shù),最后重新更新舊的點(diǎn),讓舊點(diǎn)變成一個新的位置,再次拖動的時候,就全部有了新的值,形成一個閉環(huán)。
invalidate()函數(shù)表示申請重新繪制(刷新UI)。
至此,我們就完成了點(diǎn)繪制(畫筆)的計(jì)算方法。
下一步,我們要實(shí)現(xiàn)讓畫筆的這些點(diǎn)和線呈現(xiàn)到畫板(Canvas)上:
追加實(shí)現(xiàn)Component.DrawTask的方法:
然后根據(jù)提示實(shí)現(xiàn)onDraw方法
在onDraw方法中添加如下實(shí)現(xiàn):
- canvas.drawPath(mPath, mPaint);
使用canvas的實(shí)例方法drawPath來將畫筆和路徑傳入實(shí)現(xiàn)繪制。
到這里還沒完,我們還需要做一些初始化的工作,我們寫一個Init函數(shù):
- private void Init()
- {
- mPaint = new Paint();
- mPaint.setColor(Color.WHITE);
- mPaint.setStrokeWidth(5f);
- mPaint.setStyle(Paint.Style.STROKE_STYLE);
- addDrawTask(this::onDraw);
- setTouchEventListener(this::onTouchEvent);
- }
這里將畫筆實(shí)例化,并設(shè)置顏色、粗細(xì)及樣式。然后添加繪制任務(wù)addDrawTask、設(shè)置點(diǎn)擊事件的監(jiān)聽setTouchEventListener,這倆函數(shù)分別是畫布和事件監(jiān)聽內(nèi)置的函數(shù),并非自定義的。
最后,我們需要在Draw的構(gòu)造函數(shù)中調(diào)用這個 Init()方法,這樣就可以在使用new創(chuàng)建這個Draw組件實(shí)例時自動初始化。
(三)調(diào)用工具
最后時調(diào)用我們寫的這個繪畫工具。
回到slice目錄,并打開MainAbilitySlice文件
定義各一個方向布局:
- private DirectionalLayout directionalLayout = new DirectionalLayout(this);
在onStart方法中,創(chuàng)建一個布局配置,并將配置指定給方向布局:
- LayoutConfig config = new LayoutConfig(LayoutConfig.MATCH_PARENT, LayoutConfig.MATCH_PARENT);
- directionalLayout.setLayoutConfig(config);
接著創(chuàng)建剛才寫好的Draw組件,需要添加import com.qibiao.drawdemo.Draw;
- Draw draw = new Draw(this);
設(shè)置布局配置
- draw.setLayoutConfig(config);
創(chuàng)建背景元素(這里設(shè)置為黑色,黑板嚒~)
- ShapeElement element = new ShapeElement();
- element.setRgbColor(new RgbColor(0, 0, 0));
設(shè)置背景元素
- draw.setBackground(element);
將組件添加到布局中
- directionalLayout.addComponent(draw);
設(shè)置UI內(nèi)容:
- super.setUIContent(directionalLayout);
完整代碼如下:
(四)運(yùn)行效果
運(yùn)行一個TV的遠(yuǎn)程模擬器,然后run:
手寫一個:你好,鴻蒙
[[358405]]
看起來還不錯(別在意細(xì)節(jié)~)。
不過,還不夠完美,我們再給他弄個擦除的功能。
回到Draw
添加一個重置的方法:
然后再到MainAbilitySlice中添加一個按鈕,并調(diào)用clear方法:
再次運(yùn)行已經(jīng)支持擦除。
(五)完整代碼
ok,本篇已經(jīng)務(wù)必盡量精簡了,最后放上代碼鏈接(已開源):
https://gitee.com/doufx/draw-component
?著作權(quán)歸作者和HarmonyOS技術(shù)社區(qū)共同所有,如需轉(zhuǎn)載,請注明出處,否則將追究法律責(zé)任。
想了解更多內(nèi)容,請?jiān)L問:
和華為官方合作共建的鴻蒙技術(shù)社區(qū)
https://harmonyos./#zz
網(wǎng)頁標(biāo)題:2020征文-TV10分鐘鴻蒙應(yīng)用實(shí)戰(zhàn)開發(fā):鴻蒙手繪板(含源代碼)
URL地址:http://m.fisionsoft.com.cn/article/cdspjdc.html


咨詢
建站咨詢
