【張榮超老師】鴻蒙卡片開發(fā)超細致總結(jié)
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
很多朋友都把自己的手機升級為了鴻蒙系統(tǒng)。如果你手頭有兩部或兩部以上鴻蒙系統(tǒng)的手機,就可以盡情地體驗鴻蒙的分布式能力了。如果你手頭只有一部鴻蒙系統(tǒng)的手機,不知道你有沒有感知到:與升級前相比,在用戶體驗上有哪些變化呢?細心體驗就會發(fā)現(xiàn),最大的變化非”卡片”莫屬了!卡片的功能非常強大,用戶無需打開應(yīng)用,就可以從卡片中獲取應(yīng)用相關(guān)的動態(tài)信息,而且還可以與卡片進行交互。最重要的是,在未來,卡片很可能會成為一個巨大的流量入口,從而成為第三方應(yīng)用廝殺的陣地!
一、什么是卡片
手機升級為鴻蒙系統(tǒng)之后,在某些應(yīng)用的圖標(biāo)下方顯示了一條橫線,如下圖所示:

凡是圖標(biāo)下方顯示一條橫線的應(yīng)用,都可以在桌面上添加對應(yīng)的卡片。
以“新浪新聞”這個應(yīng)用為例,用手指按下圖標(biāo)的同時往上滑,就會彈出該應(yīng)用的默認卡片,如下圖所示:

點擊卡片右上角的圖釘,就將卡片固定在了桌面上,如下圖所示:

卡片中的新聞會動態(tài)刷新。這樣,用戶無需打開應(yīng)用,就可以從卡片中獲取應(yīng)用相關(guān)的動態(tài)信息。點擊卡片中的某一條新聞,就跳轉(zhuǎn)到了應(yīng)用的相關(guān)頁面,如下圖所示:
這個卡片設(shè)計得不是很好,最好是點擊卡片中的某一條新聞,能跳轉(zhuǎn)到應(yīng)用內(nèi)該條新聞對應(yīng)的詳情頁面。
再以“音樂”這個應(yīng)用為例,用手指按下圖標(biāo)的同時往上滑,就會彈出該應(yīng)用的默認卡片,點擊卡片右上角的圖釘,就將卡片固定在了桌面上,如下圖所示:
點擊卡片中的按鈕,可以開始播放音樂和暫停播放音樂。這樣,通過與卡片進行交互,用戶無需打開應(yīng)用,就可以實現(xiàn)應(yīng)用內(nèi)的部分操作。
通過這兩個例子,我們看到:卡片是應(yīng)用內(nèi)頁面的展現(xiàn)形式,將頁面的重要信息或者操作前置到卡片上,以達到服務(wù)直達、減少體驗層級的目的。
二、卡片的數(shù)量和尺寸
我們已經(jīng)知道了:卡片是應(yīng)用內(nèi)頁面的展現(xiàn)形式,也就是應(yīng)用內(nèi)Page Ability的展現(xiàn)形式。一個應(yīng)用內(nèi)包含1~N個Page Ability,我們可以在config.json中為每個Page Ability配置0~16個卡片,而配置的每個卡片可以有1~4個尺寸,因此,每個Page Ability對應(yīng)的卡片數(shù)是0~64。
如何查看一個應(yīng)用的所有卡片呢?以“日歷”這個應(yīng)用為例,在桌面上長按其圖標(biāo),在彈出的菜單中點擊”服務(wù)卡片”,就顯示出了日歷這個應(yīng)用的所有卡片,如下圖所示:

可以通過上下滑動在卡片之間進行切換。
在所有卡片中,只有一個卡片下方的按鈕顯示為”已設(shè)為上滑卡片”,其它卡片下方的按鈕都顯示為”設(shè)為上滑卡片”。當(dāng)某個卡片被設(shè)為上滑卡片之后,在桌面上用手指按下應(yīng)用圖標(biāo)的同時往上滑,彈出的默認卡片就是該上滑卡片。比如將最后一個月視圖的卡片設(shè)為上滑卡片,如下圖所示:
點擊下方的按鈕”設(shè)為上滑卡片”,該卡片就會等待用戶將其釘在桌面上,先點擊桌面的空白處將其取消,然后用手指按下應(yīng)用圖標(biāo)的同時往上滑,彈出的默認卡片就是月視圖的卡片了。
再次查看“日歷”這個應(yīng)用的所有卡片。對于任意一個卡片,都可以點擊下方的按鈕”添加到桌面”,將其添加到桌面上。對于同一個卡片,用戶可以在桌面上重復(fù)添加多個實例,如下圖所示:
長按桌面上的某個卡片實例,在彈出的菜單中可以移除該卡片,也可以查看其對應(yīng)應(yīng)用的所有卡片。此外,用手指按下應(yīng)用圖標(biāo)的同時往上滑,然后長按彈出的默認卡片,也可以查看其對應(yīng)應(yīng)用的所有卡片。
無論一個應(yīng)用有多少個卡片,卡片只有4種尺寸,分別是:1×2的微尺寸、 2×2的小尺寸、2×4的中尺寸、4×4的大尺寸。以“相機”這個應(yīng)用為例,如下圖所示:

對于1×2的微尺寸,會占據(jù)1行2列;對于2×2的小尺寸,會占據(jù)2行2列;對于2×4的中尺寸,會占據(jù)2行4列。同理,對于4×4的大尺寸,會占據(jù)4行4列。任何一個卡片的尺寸都屬于這4種尺寸中的其中一種。
三、卡片與原子化服務(wù)
與傳統(tǒng)的需要安裝的應(yīng)用相比,原子化服務(wù)是應(yīng)用的另外一種形態(tài),他是可以提供特定功能的、免安裝的、有獨立入口的應(yīng)用形態(tài)。這里有一個非常重要的關(guān)鍵詞:免安裝。原子化服務(wù)是鴻蒙系統(tǒng)提供的一種面向未來的服務(wù)提供方式,他非常非常的重要,希望大家引起足夠的重視。
給大家舉個例子就明白什么是原子化服務(wù)了,如下圖所示:
對于某個傳統(tǒng)方式的、需要安裝的”購物應(yīng)用T”, 在按照原子化服務(wù)理念調(diào)整設(shè)計后,可以將”商品瀏覽”獨立拆分為一個原子化服務(wù)A,將”購物車”獨立拆分為一個原子化服務(wù)B,將”支付”獨立拆分為一個原子化服務(wù)C,每個原子化服務(wù)都提供了特定的功能,而且是免安裝的。用戶在用到某個原子化服務(wù)時,再按需進行安裝,系統(tǒng)程序框架會在后臺自動地從原子化服務(wù)平臺進行下載和安裝,而無需用戶顯式地手動安裝。
1個原子化服務(wù)完成1個特定的便捷服務(wù)。原子化服務(wù)由1個或多個HAP包組成,1個HAP包對應(yīng)1個FA或1個PA。每個FA或PA均可獨立運行,完成1個特定功能。原子化服務(wù)的大小不能超過10MB。
原子化服務(wù)在桌面上是沒有圖標(biāo)的,用戶可以通過”服務(wù)中心”對原子化服務(wù)進行統(tǒng)一地查看、搜索和管理。從屏幕左下角或右下角向斜上方滑動,即可進入”服務(wù)中心”,如下圖所示:


在”我的服務(wù)”板塊,展示了常用的服務(wù);在”發(fā)現(xiàn)”板塊,提供了全量的服務(wù)供用戶進行管理和使用。
原子化服務(wù)在”服務(wù)中心”的顯示形式為卡片,可以將其添加到桌面。這就是卡片與原子化服務(wù)的關(guān)系。
打開DevEco Studio,創(chuàng)建一個HarmonyOS的工程,然后選擇模板Empty Ability(JS)或Empty Ability(Java),點擊按鈕Next,進入到工程配置界面,如下圖所示:

其中,工程類型有兩種:一種是”Service”,也就是原子化服務(wù);另一種是”Application”,也就是傳統(tǒng)的應(yīng)用。此外,還可以選擇”是否在服務(wù)中心進行展示”。我們將工程類型指定為”原子化服務(wù)”,并且選擇”在服務(wù)中心進行展示”。按照上圖進行配置之后,點擊按鈕Finish以創(chuàng)建一個工程。
接下來,把鴻蒙手機連接到電腦上,對工程的主模塊entry自動簽名,如下圖所示:

簽名之后,將工程運行到鴻蒙手機上,顯示出了主界面。由于該工程的類型是”原子化服務(wù)”,所以在桌面上并沒有相應(yīng)的圖標(biāo)。由于在創(chuàng)建工程時選擇了”在服務(wù)中心進行展示”,因此,打開服務(wù)中心,就看到了相應(yīng)的入口卡片,如下圖所示:

長按卡片,可以進入相應(yīng)的服務(wù),如下圖所示:

點擊卡片,可以將其”添加到我的服務(wù)”或”添加到桌面”,如下圖所示:

好,這樣,就給大家講清楚了卡片、原子化服務(wù)和服務(wù)中心的關(guān)系。
四、卡片的整體框架
華為官方給出了一張卡片的整體框架圖,如下圖所示:

可能很多朋友看到這張圖就直接暈菜了。我們將其簡化一下,如下圖所示:

圖的最左邊是卡片提供方,要么是傳統(tǒng)應(yīng)用,要么是原子化服務(wù)。之所以將兩者稱之為卡片提供方,是因為傳統(tǒng)應(yīng)用或原子化服務(wù)中的Page Ability為卡片提供了表現(xiàn)素材,卡片是Page Ability的表現(xiàn)形式。在傳統(tǒng)應(yīng)用或原子化服務(wù)中定義了卡片的生命周期回調(diào)方法。圖的最右邊是卡片使用方,要么是桌面,要么是服務(wù)中心。之所以將兩者稱之為卡片使用方,是因為用戶通過桌面或服務(wù)中心來使用卡片。圖的中間是卡片管理服務(wù),他是卡片的大管家,是卡片提供方和卡片使用方的中介和橋梁。
以卡片的定時或定點刷新為例,如果一個卡片在config.json中配置了定時或定點刷新,具體的流程如下圖所示:

❶ timer事件會通知卡片管理服務(wù);
❷ 卡片管理服務(wù)會去卡片提供方的對象管理模塊中找到對應(yīng)的卡片提供方;
❸ 卡片提供方回調(diào)卡片的生命周期刷新方法;
❹ 卡片提供方將刷新數(shù)據(jù)返回給卡片管理服務(wù);
❺ 卡片管理服務(wù)根據(jù)卡片名稱查找卡片使用方;
❻ 卡片管理服務(wù)刷新卡片使用方的卡片。
好,了解了卡片的整體框架之后,接下來,我們就正式進入到實操部分。我會首先給大家介紹如何使用JS開發(fā)卡片,然后再來介紹如何使用Java開發(fā)卡片。
五、 使用JS開發(fā)卡片
5.1 使用模板創(chuàng)建卡片
打開DevEco Studio,創(chuàng)建一個HarmonyOS的工程,然后選擇模板Empty Ability(JS),點擊按鈕Next,進入到工程配置界面,如下圖所示:

其中,將工程類型指定為傳統(tǒng)應(yīng)用,并且不選擇”在服務(wù)中心進行展示”。按照上圖進行配置之后,點擊按鈕Finish以創(chuàng)建一個工程。
如何在一個傳統(tǒng)應(yīng)用的工程中創(chuàng)建卡片呢?在目錄entry上點擊右鍵,在彈出的菜單中選擇New,然后在彈出的子菜單中點擊Service Widget,如下圖所示:

這里的Service Widget指的就是卡片。
在模板選擇界面,選擇基本的模板Grid Pattern,點擊按鈕Next,進入到卡片配置界面,如下圖所示:

首先配置卡片的名稱和描述;然后配置卡片關(guān)聯(lián)的Page Ability;然后配置卡片的編程語言類型是JS;接下來配置卡片的JS組件名稱;最后配置卡片支持的規(guī)格,其中,2*2的小尺寸是必須要支持的,我們再勾選一個1*2的微尺寸。點擊按鈕Finish以創(chuàng)建一個卡片。
重復(fù)剛才的操作,在工程中再創(chuàng)建一個卡片,卡片配置界面如下圖所示:

其中,卡片支持的規(guī)格,除了默認的2*2小尺寸之外,再勾選一下2*4的中尺寸和4*4的大尺寸。
這樣,DevEco Studio就自動幫我們生成了一些目錄和文件。先打開js子目錄,如下圖所示:

其中,main_widget1和main_widget2是創(chuàng)建卡片時配置的JS組件名稱;index.hml中定義了卡片中包含哪些UI組件;index.css中定義了卡片中的UI組件都長什么樣;index.json中定義了卡片中動態(tài)綁定的數(shù)據(jù),此外,還可以定義click觸發(fā)的事件,稍候會給大家詳細介紹。
再打開java子目錄,如下圖所示:

其中,MainWidget1和MainWidget2是創(chuàng)建卡片時配置的卡片名稱;在MainAbility中添加了卡片的生命周期回調(diào)方法,如:onCreateForm()、onUpdateForm()、onTriggerFormEvent()、等。此外,還添加了FormControllerManager、FormController、以及兩個以Impl結(jié)尾的實現(xiàn)類,這4個文件到底有什么用呢?稍候給大家介紹。
最后,打開config.json看一下,里面自動添加了很多配置,如下圖所示:

MainAbility添加了標(biāo)簽”forms”,這里的form就是卡片的意思,和Service Widget是一回事兒。”forms”是一個數(shù)組,包含兩個元素,分別表示我們創(chuàng)建的兩個卡片。順便提一下,在前面我們有講到:“可以在config.json中為每個Page Ability配置0~16個卡片”,也就是說,數(shù)組”forms”中最多可以包含16個元素。上圖的最下方還添加了一個標(biāo)簽”js”,”js”也是一個數(shù)組,包含三個元素,其中后兩個元素就是兩個卡片對應(yīng)的js組件,”name”分別是”main_widget1”和”main_widget2”,這兩個值就對應(yīng)著上面的標(biāo)簽”forms”中”jsComponentName”的兩個值。也就是說,上面的標(biāo)簽”forms”中卡片的js組件,是在下面的標(biāo)簽”js”中定義的。
我們再來看一下上面的標(biāo)簽”forms”中卡片的配置:
“isDefault”表示該卡片是否為默認的上滑卡片,也就是用手指按下應(yīng)用圖標(biāo)的同時往上滑時彈出的卡片。
“scheduledUpdateTime”表示卡片定點刷新的時刻,采用24小時制,精確到分鐘。
“defaultDimension“表示卡片的默認尺寸規(guī)格,取值必須在下面的“supportDimensions“所配置的列表中。
“colorMode“表示卡片的主題樣式,默認值是”auto”,表示自適應(yīng),還可以取值為”dark”或”light”,分別表示深色主題和淺色主題。
“supportDimensions“表示卡片支持的尺寸規(guī)格,也就是我們在創(chuàng)建卡片時配置的尺寸規(guī)格。
“updateEnabled”表示卡片是否支持定時刷新或定點刷新,優(yōu)先選擇定時刷新。
“updateDuration“表示卡片定時刷新的周期。當(dāng)取值為0時,表示該參數(shù)不生效;當(dāng)取值為正整數(shù)N時,表示刷新周期為30*N分鐘。
接下來,我們先對工程的主模塊entry自動簽名,然后看一下運行效果。運行之后,在桌面上應(yīng)用圖標(biāo)的下方顯示了一條橫線,表示該應(yīng)用是支持卡片的,如下圖所示:

在桌面上長按應(yīng)用的圖標(biāo),在彈出的菜單中點擊”服務(wù)卡片”,就顯示出了應(yīng)用的所有卡片,如下圖所示:

上下滑動所有卡片,總共有5個,其中,名為MainWidget1的卡片有兩個,尺寸分別是1*2和2*2,名為MainWidget2的卡片有三個,尺寸分別是2*2、2*4和4*4。此外,名為MainWidget1的2*2的卡片被設(shè)為了上滑卡片,這是因為:在config.json中,將”isDefault”設(shè)為了”true”,并且將”defaultDimension”設(shè)為了” 2*2”,如下圖所示:

5.2 卡片的初始化
當(dāng)我們在桌面上長按應(yīng)用的圖標(biāo)然后顯示所有卡片的時候,MainAbility中卡片的生命周期方法onCreateForm()會被自動回調(diào),方法onCreateForm()的實現(xiàn)如下圖所示:

因為總共有5個卡片,所以方法onCreateForm()會被回調(diào)5次,如下圖所示:

在方法onCreateForm()中,分別調(diào)用intent.getLongParam()、intent.getStringParam()和intent.getIntParam()獲得了卡片的id、名稱和尺寸。此外,在方法onCreateForm()中可以進行一些卡片的初始化操作。大家想想看,現(xiàn)在應(yīng)用內(nèi)只有5個卡片,假如應(yīng)用內(nèi)有幾十個卡片,難道要把這幾十個卡片的所有初始化操作都寫在方法onCreateForm()中嗎?顯然是不好的做法!為此,通過模板自動生成的代碼中,為我們提供了FormControllerManager、FormController、XxxImpl這幾個類。其中,F(xiàn)ormControllerManager是卡片管理器的大管家;FormController是卡片的管理器,他是一個抽象類;XxxImpl實現(xiàn)了FormController,MainWidget1Impl是名為MainWidget1的卡片對應(yīng)的卡片控制器,MainWidget2Impl是名為MainWidget2的卡片對應(yīng)的卡片控制器。這樣,就可以根據(jù)卡片的名稱對卡片進行獨立控制了。在方法onCreateForm()中,首先得到FormControllerManager的實例,然后根據(jù)卡片ID得到對應(yīng)的卡片控制器,也就是對應(yīng)的XxxImpl的實例,最后調(diào)用對應(yīng)的XxxImpl中的方法bindFormData()。
打開MainWidget1Impl,方法bindFormData()中的代碼如下所示:

根據(jù)卡片的尺寸,分別設(shè)置了兩個變量”mini”和”dim2X4”的值,這兩個變量是子目錄main_widget1中的index.json中的兩個變量。這里順便說一下,在index.hml中,很多變量都使用兩個花括號括了起來,這些變量的值是在程序的運行過程中動態(tài)確定的,這種技術(shù)稱之為動態(tài)綁定。這些變量的初始值在index.json中的標(biāo)簽”data”中進行了定義。所以,在方法bindFormData()中,根據(jù)卡片的尺寸修改了兩個動態(tài)綁定的變量的值。我們對自動生成的代碼再修改一下,如下圖所示:

同時,對MainWidget2Impl中的方法bindFormData()也修改一下,如下圖所示:

運行工程,顯示所有卡片,如下圖所示:

所有卡片的標(biāo)題都被修改了(尺寸最小的卡片除外,因為他本來就不顯示標(biāo)題)。
5.3 卡片的定點/定時刷新
接下來,我們試一下卡片的定點刷新。打開config.json,先將MainWidget2對應(yīng)的標(biāo)簽”updateDuration”修改為0,以關(guān)閉定時刷新。對于標(biāo)簽“scheduledUpdateTime”設(shè)定的時刻,當(dāng)?shù)竭_之后,MainAbility中卡片的回調(diào)方法onUpdateForm()就會被自動調(diào)用,如下圖所示:

在方法體的最后,調(diào)用了卡片控制器的方法updateFormData()。打開MainWidget2Impl,在方法updateFormData()中,添加如下代碼:

首先,將要刷新的數(shù)據(jù)存放在一個ZSONObject實例中,然后,將其封裝在一個FormBindingData的實例bindingData中,最后,調(diào)用MainAbility的方法updateForm(),并將bindingData作為第二個實參。
打開config.json,將標(biāo)簽“scheduledUpdateTime”的值修改為當(dāng)前時刻的兩分鐘之后。
運行工程,將ManWidget2對應(yīng)的三個卡片都添加到桌面上,當(dāng)?shù)竭_設(shè)定的定點時刻之后,三個卡片的標(biāo)題都刷新了,如下圖所示:


5.4 卡片的跳轉(zhuǎn)事件
對于桌面上名為MainWidget2的三個卡片,接下來我們要實現(xiàn)的功能是:點擊任意一個卡片中左上方的圖片,都跳轉(zhuǎn)到SecondAbility對應(yīng)的頁面。
新建一個名為SecondAbility的Page Ability,其所在的包是com.zrc.demos。
打開子目錄main_widget2中的index.json,添加如下配置:

其中,標(biāo)簽”actions”用于定義所有的事件,目前只定義了一個名為“startSecondAbility”的事件。將標(biāo)簽“action”的值設(shè)置為“router”,表示該事件是一個跳轉(zhuǎn)事件。標(biāo)簽“abilityName”的值指定了跳轉(zhuǎn)的目標(biāo)Ability。標(biāo)簽“params”的值指定了跳轉(zhuǎn)時攜帶的數(shù)據(jù)。
打開子目錄main_widget2中的index.hml,在標(biāo)簽image中添加一個屬性onclick,并將值設(shè)置為剛剛在index.json中定義的action的名稱“startSecondAbility”,如下圖所示:

打開SecondAbilitySlice,在回調(diào)方法onStart()中獲取跳轉(zhuǎn)時攜帶的數(shù)據(jù),如下圖所示:

首先,根據(jù)key的值“params”獲得一個字符串格式的JSON數(shù)據(jù);然后,調(diào)用ZSONObject.stringToZSON()將其轉(zhuǎn)換為一個ZSONObject的實例data;最后,從data中分別獲得”param1”和”param2”這兩個key對應(yīng)的value。
運行工程,將名為MainWidget2的任意一個卡片添加到桌面上,點擊卡片中左上方的圖片,跳轉(zhuǎn)到了SecondAbility對應(yīng)的頁面,打印出的log如下所示:

5.5 卡片的消息事件
除了支持跳轉(zhuǎn)事件,卡片還支持消息事件。當(dāng)觸發(fā)消息事件時,卡片所對應(yīng)Page Ability的生命周期方法onTriggerFormEvent()會被自動回調(diào)。接下來我們要實現(xiàn)的功能是:對于名為MainWidget2的任意一個卡片,點擊卡片的空白處,都會回調(diào)方法onTriggerFormEvent()。
打開子目錄main_widget2中的index.json,添加如下配置:

在標(biāo)簽”actions”中再定義了一個名為“sendMessageEvent”的事件。將標(biāo)簽“action”的值設(shè)置為“message”,表示該事件是一個消息事件。標(biāo)簽“params”中定義了相關(guān)的數(shù)據(jù)。
打開子目錄main_widget2中的index.hml,在第6行的標(biāo)簽div中添加一個屬性onclick,并將值設(shè)置為剛剛在index.json中定義的action的名稱“sendMessageEvent”,如下圖所示:

通過模板創(chuàng)建卡片時自動生成的方法onTriggerFormEvent(),如下圖所示:

在方法體的最后,調(diào)用了卡片控制器的方法onTriggerFormEvent()。因此,打開MainWidget2Impl,在方法onTriggerFormEvent()中,添加如下代碼:

首先,message是一個字符串格式的JSON數(shù)據(jù);然后,調(diào)用ZSONObject.stringToZSON()將message轉(zhuǎn)換為一個ZSONObject的實例data;最后,從data中分別獲得”p1”和”p2”這兩個key對應(yīng)的value。
運行工程,將名為MainWidget2的任意一個卡片添加到桌面上,點擊卡片的空白處,卡片所對應(yīng)Page Ability的生命周期方法onTriggerFormEvent()被自動回調(diào),打印出的log如下所示:

六、使用Java開發(fā)卡片
請不要跳過前面的“使用JS開發(fā)卡片”,因為前后是有聯(lián)系的,即便你對JS不熟悉,相信你也可以看懂的。此外,大家在學(xué)習(xí)接下來的內(nèi)容時,請注意與前面的“使用JS開發(fā)卡片”進行對比。
6.1 使用模板創(chuàng)建卡片
首先,我們使用模板創(chuàng)建一個Java類型的卡片。在目錄entry上點擊右鍵,在彈出的菜單中選擇New,然后在彈出的子菜單中點擊Service Widget,在模板選擇界面,選擇基本的模板Grid Pattern,點擊按鈕Next,進入到卡片配置界面,如下圖所示:

其中,配置卡片的編程語言類型為JAVA。為了與名為MainWidget2的三個卡片進行對比,我們也配置三個尺寸:2*2、2*4、4*4。
這樣,DevEco Studio就自動幫我們生成了一些目錄和文件。
打開java子目錄,自動創(chuàng)建了一個子目錄mainwidget3,并且自動創(chuàng)建了一個文件MainWidget3Impl以作為卡片MainWidget3的控制器,如下圖所示:

打開js子目錄,沒有自動創(chuàng)建任何目錄和文件,而是在子目錄layout中自動創(chuàng)建了3個布局文件,如下圖所示:

這是3個不同尺寸卡片的布局文件,通過文件名就能看出每個布局文件所對應(yīng)的卡片尺寸。布局文件里定義了卡片中包含哪些UI組件以及UI組件都長什么樣,因此,布局文件就相當(dāng)于子目錄js中的hml文件和css文件。
最后,打開config.json看一下,里面自動添加了一些配置,如下圖所示:

與js不同的是,java卡片要分別配置”landscapeLayouts”和“portraitLayouts”,分別表示卡片對應(yīng)的橫向布局文件和豎向布局文件。值得注意的是:配置的數(shù)組中的元素要與“supportDemensions”中的元素一一對應(yīng)。
運行工程,在桌面上長按應(yīng)用的圖標(biāo),在彈出的菜單中點擊”服務(wù)卡片”,就顯示出了應(yīng)用的所有卡片,現(xiàn)在總共有8個,其中,名為MainWidget3的卡片有3個。
6.2 卡片的初始化
當(dāng)我們在桌面上長按應(yīng)用的圖標(biāo)然后顯示所有卡片的時候,MainAbility中卡片的生命周期方法onCreateForm()會被自動回調(diào),因為總共有8個卡片,所以方法onCreateForm()會被回調(diào)8次。在方法體的最后,調(diào)用了對應(yīng)的XxxImpl中的方法bindFormData()。
打開MainWidget3Impl,方法bindFormData()中的代碼如下所示:

三個卡片的布局文件都放在了一個map中,根據(jù)卡片的尺寸得到對應(yīng)的布局文件,然后創(chuàng)建一個提供者卡片信息ProviderFormInfo的實例并將其返回了。
接下來,我們實現(xiàn)與MainWidget2相同的功能:修改三個卡片的標(biāo)題。首先,在卡片對應(yīng)的三個布局文件中,都為卡片標(biāo)題對應(yīng)的組件Text添加一個id,如下圖所示:

然后,在MainWidget3Impl中添加一個靜態(tài)常量,如下圖所示:

在返回ProviderFormInfo的實例之前,先根據(jù)卡片的尺寸修改對應(yīng)的標(biāo)題,如下圖所示:

首先,構(gòu)造一個ComponentProvider的實例,用于表示一個Java卡片實例;然后,根據(jù)卡片的尺寸修改布局文件中標(biāo)題的值,其中,標(biāo)題是通過布局文件中組件Text對應(yīng)的id進行指定的;最后,調(diào)用providerFormInfo的方法mergeActions()并且將componentProvider作為實參傳過去。
運行工程,名為MainWidget3的三個卡片的標(biāo)題都被修改了,如下圖所示:

6.3 卡片的定點/定時更新
接下來,我們試一下卡片的定點刷新。打開config.json,先將MainWidget3對應(yīng)的標(biāo)簽”updateDuration”修改為0,以關(guān)閉定時刷新。對于標(biāo)簽“scheduledUpdateTime”設(shè)定的時刻,當(dāng)?shù)竭_之后,MainAbility中卡片的回調(diào)方法onUpdateForm()就會被自動調(diào)用,在方法體的最后,調(diào)用了卡片控制器的方法updateFormData()。打開MainWidget3Impl,在方法updateFormData()中,添加如下代碼:

首先,構(gòu)造一個ComponentProvider的實例,用于表示一個Java卡片實例,傳入的第一個實參是根據(jù)卡片尺寸得到的布局文件。然后,調(diào)用方法setText()修改卡片的標(biāo)題;最后,調(diào)用MainAbility的方法updateForm(),并將componentProvider作為第二個實參。
打開config.json,將標(biāo)簽“scheduledUpdateTime”的值修改為當(dāng)前時刻的兩分鐘之后。
運行工程,將ManWidget3對應(yīng)的三個卡片都添加到桌面上,當(dāng)?shù)竭_設(shè)定的定點時刻之后,三個卡片的標(biāo)題都刷新了。
6.4 卡片的事件
與JS不同的是,Java卡片是通過IntentAgent來設(shè)置事件的。以跳轉(zhuǎn)事件為例,接下來我們實現(xiàn)的功能是:對于名為MainWidget3的、尺寸為2*4的卡片,當(dāng)點擊標(biāo)題時跳轉(zhuǎn)到SecondAbility對應(yīng)的頁面。
打開MainWidget3Impl,在方法bindFormData()中,當(dāng)卡片尺寸為2*4時,調(diào)用componentProvider的方法setIntentAgent(),傳入的第一個實參是標(biāo)題在布局文件中的id,第二個實參是用于頁面跳轉(zhuǎn)的IntentAgent實例。代碼如下所示:

接下來,定義方法getStartAbilityIntentAgent()的具體實現(xiàn),代碼如下所示:

運行工程,將名為MainWidget3的、尺寸為2*4的卡片添加到桌面,點擊卡片中的標(biāo)題,跳轉(zhuǎn)到了SecondAbility對應(yīng)的頁面。
七、開發(fā)卡片到底該使用JS還是使用Java
官方文檔中給出了JS卡片和Java卡片的場景能力差異,如下表所示:

通過該表可以看出:
JS卡片比JAVA卡片支持的控件和能力都更豐富。
Java卡片適合作為一個直達入口,沒有復(fù)雜的頁面和事件。
JS卡片適合有復(fù)雜界面的卡片。
我個人更推薦使用JS卡片,因為使用起來更靈活、更簡單、功能更強大!
文章相關(guān)附件可以點擊下面的原文鏈接前往下載
原文鏈接:https://harmonyos.51cto.com/posts/4776
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)