華為云享專家,InfoQ簽約作者,阿里云專家博主,51CTO博客首席體驗(yàn)官,開源項(xiàng)目GVA成員之一,專注于大前端技術(shù)的分享,包括Flutter,小程序,安卓,VUE,JavaScript。
日常我們?cè)陂_發(fā)項(xiàng)目時(shí),為了項(xiàng)目快速的開發(fā)和迭代,難免會(huì)用到H5頁面。使用鴻蒙進(jìn)行項(xiàng)目開發(fā)時(shí),也一樣免不了要加載H5頁面,在移動(dòng)開發(fā)中打開H5頁面需要使用WebView組件。同時(shí),為了和H5頁面進(jìn)行數(shù)據(jù)交換,有時(shí)候還需要借助JSBridge來實(shí)現(xiàn)客戶端與H5之間的通訊。
那么鴻蒙之中用到的技術(shù)是什么呢?WebView
在此之前,先看一個(gè)報(bào)錯(cuò)
App Launch: The Huawei Lite Simulator supports only Lite projects.
這是什么原因呢,其實(shí)簡(jiǎn)單,就是你沒有登陸
所以解決這個(gè)的問題就是你重新登錄就好了。
漢化(V3.0 Beta2(2021-12-31)版本以上支持)
還有一個(gè)問題可能就是目前編輯器大家看著不太習(xí)慣,需要漢化一下,那么如何漢化呢,結(jié)合Androidstudio的經(jīng)驗(yàn),分為如下幾步
第一步點(diǎn)擊File-setting
第二步plugins里面選擇如圖所示的插件,并安裝。
第三步,重啟,漢化完成
第一步創(chuàng)建項(xiàng)目
點(diǎn)擊next
第二步等依賴安裝安裝完成
第三步打開模擬器
點(diǎn)擊登錄,打開瀏覽器授權(quán)
選擇p40
啟動(dòng)模擬器
第五步開始正文
接下來開始正文。
應(yīng)用預(yù)覽:
點(diǎn)擊"打開網(wǎng)址"按鈕會(huì)加載上方網(wǎng)址的Web頁面,通過后退"和"前進(jìn)"按鈕實(shí)現(xiàn)Web頁面間的導(dǎo)航。
點(diǎn)擊"加載本地網(wǎng)頁"按鈕加載本地Web頁面,點(diǎn)擊"發(fā)送消息給本地html"或者Web頁面中的"調(diào)用Java方法"按鈕,實(shí)現(xiàn)應(yīng)用與Web頁面間的交互。
這里是http訪問方式,鴻蒙的默認(rèn)是https訪問模式,如果您的請(qǐng)求網(wǎng)址是http開頭的,可以繼續(xù)查看后面的教程。
1. 增加一個(gè)WebView組件
步驟 1 - 在"resources/base/layout/ability_main.xml"文件中創(chuàng)建WebView,示例代碼如下:
ohos:id
=
"$+id:webview"
ohos:height
=
"match_parent"
ohos:width
=
"match_parent"
>
步驟 2 - 在"slice/MainAbilitySlice.java"文件中通過如下方式獲取WebView對(duì)象,示例代碼如下:
WebView webview = (WebView) findComponentById(ResourceTable.Id_webview);
2. 通過WebView加載Web頁面
WebView加載頁面分為加載Web頁面和加載本地Web頁面兩種情況,接下來我們將分別進(jìn)行介紹。
1.WebView加載網(wǎng)絡(luò)Web頁面
跟Android類似,要訪問網(wǎng)絡(luò),我們首先要配置網(wǎng)絡(luò)訪問權(quán)限,在config.json的"module"節(jié)點(diǎn)最后,添加上網(wǎng)絡(luò)權(quán)限代碼
module": {
......
"reqPermissions": [
{
"name": "ohos.permission.INTERNET"
}
]
}
2 設(shè)置訪問模式
鴻蒙的默認(rèn)是https訪問模式,如果您的請(qǐng)求網(wǎng)址是http開頭的,請(qǐng)?jiān)赾onfig.json文件中的deviceConfig下,添加如下設(shè)置
"deviceConfig": {
"default": {
"network": {
"cleartextTraffic": true
}
}
},
在"slice/MainAbilitySlice.java"文件中通過webview.load(String url)方法訪問具體的Web頁面,通過WebConfig類對(duì)WebView組件的行為進(jìn)行配置,示例代碼如下:
WebConfig webConfig = webview.getWebConfig();
// WebView加載URL,其中urlTextField為輸入U(xiǎn)RL的TextField組件
webview.load(urlTextField.getText());
在Web頁面進(jìn)行鏈接跳轉(zhuǎn)時(shí),WebView默認(rèn)會(huì)打開目標(biāo)網(wǎng)址,通過WebAgent對(duì)象可以定制該行為,示例代碼如下:
webview
.
setWebAgent
(
new
WebAgent
() {
@Override
public
boolean
isNeedLoadUrl
(
WebView
webView
,
ResourceRequest
request
) {
if
(
request
==
null
||
request
.
getRequestUrl
()
==
null
) {
LogUtil
.
info
(
TAG
,
"WebAgent isNeedLoadUrl:request is null."
);
return
false
;
}
String
url
=
request
.
getRequestUrl
().
toString
();
if
(
url
.
startsWith
(
"http:"
)
||
url
.
startsWith
(
"https:"
)) {
webView
.
load
(
url
);
return
false
;
}
else
{
return
super
.
isNeedLoadUrl
(
webView
,
request
);
}
}
});
除此之外,WebAgent對(duì)象還提供了相關(guān)的回調(diào)函數(shù)以觀測(cè)頁面狀態(tài)的變更,如onLoadingPage、onPageLoaded、onError等方法。WebView提供Navigator類進(jìn)行歷史記錄的瀏覽和處理,通過getNavigator()方法獲取該類的對(duì)象,使用canGoBack()或canGoForward()方法檢查是否可以向后或向前瀏覽,使用goBack()或goForward()方法向后或向前瀏覽,示例代碼如下:
Navigator navigator = webView.getNavigator();
if (navigator.canGoBack()) {
navigator.goBack();
}
if (navigator.canGoForward()) {
navigator.goForward();
}
3.WebView加載本地Web頁面
將本地的HTML文件放在"resources/rawfile/"目錄下,在本教程中命名為test.html。在HarmonyOS系統(tǒng)中,WebView要訪問本地Web文件,需要通過DataAbility的方式進(jìn)行訪問,DataAbility的具體使用方法可以參考開發(fā)
DataAbility,關(guān)于DataAbility的相關(guān)知識(shí),后面也會(huì)繼續(xù)展示,誰讓他是最重要的內(nèi)容呢。
在"entry/src/main/config.json"中完成DataAbility的聲明,示例代碼如下:
module": {
......
"abilities": [
{
"name": "com.huawei.codelab.DataAbility",
"type": "data",
"uri": "dataability://com.example.harmonyosdemo.DataAbility"
}
]
}
另外需要實(shí)現(xiàn)一個(gè)DataAbility,通過實(shí)現(xiàn)openRawFile(Uri uri, String mode)方法,完成WebView對(duì)本地Web頁面的訪問,示例代碼如下:
public class DataAbility extends Ability { ... @Override public RawFileDescriptor openRawFile(Uri uri, String mode) throws FileNotFoundException { if (uri == null) {; return super.openRawFile(uri, mode); } String path = uri.getEncodedPath(); int splitIndex = path.indexOf('/', 1); String providerName = Uri.decode(path.substring(1, splitIndex)); String rawFilePath = Uri.decode(path.substring(splitIndex + 1)); RawFileDescriptor rawFileDescriptor = null; try { rawFileDescriptor = getResourceManager().getRawFileEntry(rawFilePath).openRawFileDescriptor(); } catch (IOException e) { // 異常處理 } return rawFileDescriptor; } }
在"slice/MainAbilitySlice.java"中聲明需要訪問的文件路徑,通過webview.load(String url)方法加載本地Web頁面,可以通過WebConfig類的對(duì)象對(duì)WebView訪問DataAbility的能力進(jìn)行配置,示例代碼如下:
private static final String URL_LOCAL = "dataability://com.huawei.codelab.DataAbility/resources/rawfile/test.html"; // 配置是否支持訪問DataAbility資源,默認(rèn)為true webConfig.setDataAbilityPermit(true); webview.load(URL_LOCAL);
4. 實(shí)現(xiàn)應(yīng)用與WebView中的Web頁面間的通信
本教程以本地Web頁面"resources/rawfile/test.html"為例介紹如何實(shí)現(xiàn)應(yīng)用與WebView中的Web頁面間交互。 首先需要對(duì)WebConfig進(jìn)行配置,使能WebView與Web頁面JavaScript交互的能力,示例代碼如下:
// 配置是否支持JavaScript,默認(rèn)值為false webConfig.setJavaScriptPermit(true);
1.應(yīng)用調(diào)用Web頁面
在"resources/rawfile/test.html"中編寫callJS方法,待應(yīng)用調(diào)用,示例代碼如下:
// 應(yīng)用調(diào)用Web頁面 function callJS(message) { alert(message); }
在"slice/MainAbilitySlice.java"中實(shí)現(xiàn)應(yīng)用對(duì)JavaScript的調(diào)用,示例代碼如下:
webview.executeJs("javascript:callJS('這是來自JavaSlice的消息')", msg -> { // 在這里處理Js的方法的返回值 });
我們可以通過setBrowserAgent方法設(shè)置自定義BrowserAgent對(duì)象,以觀測(cè)JavaScript事件及通知等,通過復(fù)寫onJsMessageShow方法來接管Web頁面彈出Alert對(duì)話框的事件,示例代碼如下:
webview.setBrowserAgent(new BrowserAgent(this) { @Override public boolean onJsMessageShow(WebView webView, String url, String message, boolean isAlert, JsMessageResult result) { LogUtil.info(TAG,"BrowserAgent onJsMessageShow : " + message); if (isAlert) { // 將Web頁面的alert對(duì)話框改為ToastDialog方式提示 new ToastDialog(getApplicationContext()).setText(message).setAlignment(LayoutAlignment.CENTER).show(); // 對(duì)彈框進(jìn)行確認(rèn)處理 result.confirm(); return true; } else { return super.onJsMessageShow(webView, url, message, isAlert, result); } } });
2.Web頁面使用JavaScript調(diào)用應(yīng)用
在"resources/rawfile/test.html"中編寫按鈕,當(dāng)按鈕被點(diǎn)擊時(shí)實(shí)現(xiàn)JavaScript對(duì)應(yīng)用的調(diào)用,示例代碼如下:
調(diào)用Java方法 function sendData() { if (window.JsCallJava && window.JsCallJava.call) { // Web頁面調(diào)用應(yīng)用 var rst = window.JsCallJava.call("這個(gè)是來自本地Web頁面的消息"); } else { alert('發(fā)送消息給WebviewSlice失敗'); } }
在"slice/MainAbilitySlice.java"中實(shí)現(xiàn)應(yīng)用對(duì)JavaScript發(fā)起的調(diào)用的響應(yīng),示例代碼如下:
private static final String JS_NAME = "JsCallJava"; webview.addJsCallback(JS_NAME, str -> { // 處理接收到的JavaScript發(fā)送來的消息,本教程通過ToastDialog提示確認(rèn)收到Web頁面發(fā)來的消息 new ToastDialog(this).setText(str).setAlignment(LayoutAlignment.CENTER).show(); // 返回給JavaScript return "Js Call Java Success"; });
總結(jié)
通過上面的完整代碼,我們已經(jīng)完成了webbiew的基本使用
倉(cāng)庫地址:https://github.com/ITmxs/hm_webview
感謝沒用的喵叔指出的問題
個(gè)人認(rèn)為這兩句有點(diǎn)多余,默認(rèn)處理http和https的邏輯應(yīng)該就是return true,在父類里已經(jīng)實(shí)現(xiàn)了。所以,這個(gè)方法直接改成這樣:
webview.setWebAgent(new WebAgent() { @Override public boolean isNeedLoadUrl(WebView webView, ResourceRequest request) { if (request == null || request.getRequestUrl() == null) { return false; } return super.isNeedLoadUrl(webView, request); } });
第二步刪除默認(rèn)代碼
打開index.hml文件,里面有默認(rèn)代碼如下:
山茶
第三步,開始學(xué)習(xí)
首先將圖片放到common文件夾下面的images里面,注意,我的圖片文件名是flutter.png,
從上面布局效果圖可以看到,界面主要由image組件和text組件組成,我們現(xiàn)在index.html中添加image組件和text組件,并添加對(duì)應(yīng)的class,用于設(shè)置組件的顯示效果,代碼如下:
translate
rotate
rotateY
scale
opacity
第四步,為頁面設(shè)計(jì)樣式
在這個(gè)任務(wù)中,我們將一起為任務(wù)二中寫好的頁面添加樣式,上面所有的組件都定義了class屬性,它對(duì)應(yīng)的樣式都定義在index.css中,有關(guān)css更多的知識(shí)可以參考css語法參考。 這部分定義了整個(gè)頁面中各個(gè)組件的樣式。在index.css中先添加如下代碼:
.container { background-color: #F8FCF5; flex-direction: column; justify-content: center; align-items: center; } .img { margin-top: 10px; height: 100px; width: 100px; animation-timing-function: ease; animation-duration: 2s; animation-delay: 0s; animation-fill-mode: forwards; animation-iteration-count: infinite; } .text { font-size: 20px; } .img-translate { animation-name: translateAnim; } .img-rotate { animation-name: rotateAnim; } .img-rotateY { animation-name: rotateYAnim; } .img-scale { animation-name: scaleAnim; } .img-mixes { animation-name: mixesAnim; } .img-opacity { animation-name: opacityAnim; } /*從-100px平移到100px*/ @keyframes translateAnim { from { transform: translate(-100px); } to { transform: translate(100px); } } /*從0°旋轉(zhuǎn)到360°*/ @keyframes rotateAnim { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } /*沿Y軸旋轉(zhuǎn),從0°旋轉(zhuǎn)到360°*/ @keyframes rotateYAnim { from { transform: rotateY(0deg); } to { transform: rotateY(360deg); } } /*從0倍縮放到1.2倍大小*/ @keyframes scaleAnim { from { transform: scale(0); } to { transform: scale(1.2); } } /*透明度從0變化到1*/ @keyframes opacityAnim { from { opacity: 0; } to { opacity: 1; } }
通過一個(gè)代碼示例,實(shí)現(xiàn)image組件的平移、縮放、旋轉(zhuǎn)和透明度變化動(dòng)效。希望通過本教程,各位開發(fā)者可以對(duì)JS通用動(dòng)畫樣式具有更深刻的認(rèn)識(shí)。
在實(shí)現(xiàn)過程過也遇到一些問題,順便做個(gè)記錄
使用標(biāo)簽引入的本地圖片無法加載
使用標(biāo)簽引入本地圖片,但圖片無法加載的可能情況有三種:
沒有給圖片設(shè)置寬度和高度,需要在對(duì)應(yīng)的“page”目錄下的 css 樣式文件中設(shè)置圖 片的寬高。
使用標(biāo)簽的圖片不會(huì)自動(dòng)縮放,圖片寬高超過組件的寬高會(huì)自動(dòng) 截取。
圖片引入路徑錯(cuò)誤。圖片引入的路徑必須是項(xiàng)目編譯后的靜態(tài)文件的路徑。 ? 在導(dǎo)入圖片或添加/刪除頁面后沒有重新編譯。
審核編輯:湯梓紅
-
華為
+關(guān)注
關(guān)注
216文章
34511瀏覽量
252386 -
鴻蒙系統(tǒng)
+關(guān)注
關(guān)注
183文章
2637瀏覽量
66512
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論