Android軟件適配遙控器需求-案例經驗分享

不分大屏產品需要有遙控器功能,這里分享部分實戰經驗

文章目錄

  • 前言
  • 一、案例部分效果圖
  • 二、項目基礎架構
  • 三、焦點基礎知識
    • 適配遙控器基礎-焦點問題
    • 焦點管理
      • 明確焦點狀態
        • 布局實現
        • 硬編碼實現
        • 引入第三方自定義組件實現
      • 焦點順序
        • 作用
      • 初始焦點 requestFocus
    • 按鍵處理
    • 獲取當前焦點
  • 四、實際開發技能分享
    • 處理焦點注意實現
    • RecycleView 案例分析
  • 總結


前言

十多年的Android軟件開發中,基本上都是做方案上的軟件產品。 對于 電視、投影、閨蜜機 上面的軟件 都有遙控器控制的需求,就需要自己的Android App能夠受遙控器控制。 這里舉一個案例,分享一下開發中的部分經驗。 也方便自己下次開發直接復用經驗,高效開發。


一、案例部分效果圖

當前分享案例中部分效果圖如下

在這里插入圖片描述

在這里插入圖片描述
在這里插入圖片描述

二、項目基礎架構

為什么要簡單列舉一下架構圖,其實不同的UI架構會遇到各種不一樣的問題,這里針對性的從列舉項目上展示一下架構,方便分析和理解部分闡明的問題

在這里插入圖片描述

三、焦點基礎知識

適配遙控器基礎-焦點問題

焦點管理

軟件App 適配遙控器,需要用遙控器的功能,實際上就是處理焦點問題。當UI獲取焦點時候、用遙控器上下左右按鍵移動到某一個UI圖標識貨,UI圖標必須差異化顯示出來,表示選中狀態,進而遙控器點擊ok 等,實際上就是點擊這個UI的操作。

明確焦點狀態

確保UI元素有清晰的焦點視覺效果(放大、邊框、陰影等)
如上描述,其實就是一個UI組件選中的效果。 這里我理解有三種表現形式

布局實現

比如我們開發中常見的,在獲取焦點 state_focused = true ,時候給于不同的背景、顏色 等突出顯示出來。

<Buttonandroid:id="@+id/button"android:focusable="true"android:background="@drawable/button_background"/><!-- drawable/button_background.xml -->
<selector xmlns:android="http://schemas.android.com/apk/res/android"><item android:state_focused="true" android:drawable="@drawable/button_focused"/><item android:drawable="@drawable/button_normal"/>
</selector>
硬編碼實現

這里舉個例子如下,設置UI組件的FocusChange 事件,對獲取焦點和失去焦點進行UI不同渲染,達到焦點選中效果,無交點正常顯示效果。

 binding.selectOk.setOnFocusChangeListener { v, hasFocus ->val roundView: RoundTextView = v as RoundTextViewif (hasFocus) {roundView.setStrokeWidthColor(5f, Color.parseColor("#EEEE00"))} else {roundView.setStrokeWidthColor(5f, Color.parseColor("#00000000"))}}holder.vb.root.setOnFocusChangeListener { v, hasFocus ->val roundView: RoundConstraintLayout = v as RoundConstraintLayoutif(hasFocus){roundView.setStrokeWidthColor(5f, Color.parseColor("#EEEE00"))focusPos=positionLog.d(TAG," focusPos:${focusPos}")RightAppInfoLiveData.value= RightAppInfo(focusPos,mCenterAppDataList.size)}else{roundView.setStrokeWidthColor(5f, Color.parseColor("#00000000"))Log.d(TAG,"no focusPos:${focusPos}")focusPos=-1RightAppInfoLiveData.value= RightAppInfo(focusPos,mCenterAppDataList.size)}}
引入第三方自定義組件實現

只是作為一個UI組件使用,第三方組件和核心功能就是在獲取焦點時候突出顯示而已,和 布局表現及 硬編碼實現方式并無區別。

焦點順序

設置合理的焦點移動順序(android:nextFocusUp/Down/Left/Right),為什么要有這個東西呢? 舉例在架構圖中,分三頁面,無論那個頁面都有很多UI組件,如何實現遙控器按 上、下、左、右按鍵時候,UI組件選中按照自己意愿活著業務定義來切換不同UI選中狀態呢?

這個時候,焦點移動順序就起到作用了,下面列舉一下實際用法,其實就是在布局文件中設置的。

作用
  • 實現UI焦點移動順序
  • 對邊角的UI組件,指向自己,這樣就可以規避焦點不見了的問題,規避反人類的體驗。
    實際使用 簡單 如下:

在這里插入圖片描述

在這里插入圖片描述

初始焦點 requestFocus

為什么會有這個方法, 為什么需要? 比如說 進行界面切換的時候,如架構圖中從一個界面切換到另外一個界面、點擊一個圖標進入另外一個界面。 在新的界面焦點在哪里是不確定的或者說在新的界面,是沒有焦點的。 那么最好初始化一個UI具備焦點。 這樣遙控器按鍵時候直接上下左右進行切換,規避沒有焦點時候或者焦點不確定時候需要多按好多次 才有UI獲取焦點顯示出來,體驗和業務需要的。

比如,架構圖中,第一頁切換到第二頁、第二頁切換到第三頁、第三頁切換到第二頁、第二頁切換到第一頁,如何實現焦點初始化呢?
在 頁面onResume 方法中,讓指定的UI初始化一次焦點,去獲取焦點一次。
在這里插入圖片描述
在這里插入圖片描述

在這里插入圖片描述

按鍵處理

我們為什么需要處理按鍵,遙控器的本身其實就是KeyEvent 事件,映射的其實就是物理按鍵的功能。 那么當keyevent 事件通過遙控器觸發后,做什么業務邏輯,那就是上層需要處理的事情了。 這就是為什么我們需要按鍵處理了。
對于很多遙控器,基本功能通用;專用的KeyEvent 是通過定制實現(比如 點擊遙控器一個按鍵就是要直接打開抖音、長按遙控器進行語音控制呀,這些就是定制的功能)

下面代碼列舉了部分源碼,監聽左右按鍵最核心的功能是 需要翻頁的功能。 遙控器沒有翻頁的物理按鍵,通過當前焦點,是否是邊角焦點結合按鍵監聽方向,實現是否翻頁、翻到哪一頁的功能。

  override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {when (keyCode) {KeyEvent.KEYCODE_DPAD_UP -> {Log.d(TAG," KEYCODE_DPAD_UP")val rootview = window.decorViewval focusView = rootview.findFocus()Log.i(TAG, "===當前獲取焦點的View===${focusView}")//return true // 返回true表示事件已被處理val focused = currentFocusfocusView?.let {if(viewPager.currentItem==1&&(focusView.id== R.id.cl_homeleft_second||focusView.id== R.id.cl_homeleft_center||focusView.id== R.id.cl_homeleft_first )){Log.d(TAG,"KEYCODE_DPAD_UP  在vp 第2 頁面,但是焦點卻在第一頁面,那么 request 一次")//homeCenterFragment.binding.clTouping.requestFocus()try{homeCenterFragment.viewBinding?.let { vBing->vBing.clTouping.requestFocus()}}catch (e:Exception){Log.d(TAG," 暫時 未初始化 homeCenterFragment.viewBinding ")e.printStackTrace()}//   viewPager.currentItem=1}}}KeyEvent.KEYCODE_DPAD_DOWN -> {Log.d(TAG," KEYCODE_DPAD_DOWN")val rootview = window.decorViewval focusView = rootview.findFocus()val focused = currentFocusLog.i(TAG, "===當前獲取焦點的View===${focusView}")focusView?.let {if(viewPager.currentItem==1&&(focusView.id== R.id.cl_homeleft_second||focusView.id== R.id.cl_homeleft_center||focusView.id== R.id.cl_homeleft_first )){Log.d(TAG,"KEYCODE_DPAD_DOWN 在vp 第2 頁面,但是焦點卻在第一頁面,那么 request 一次")//homeCenterFragment.binding.clTouping.requestFocus()// viewPager.requestFocus()try{homeCenterFragment.viewBinding?.let { vBing->vBing.clTouping.requestFocus()}}catch (e:Exception){Log.d(TAG," 暫時 未初始化 homeCenterFragment.viewBinding ")e.printStackTrace()}//viewPager.currentItem=1}}}KeyEvent.KEYCODE_DPAD_LEFT -> {Log.d(TAG," KEYCODE_DPAD_LEFT")val rootview = window.decorViewval focusView = rootview.findFocus()Log.i(TAG, "===當前獲取焦點的View===${focusView}")focusView?.let {if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {if(focusView.id== R.id.cl_clock||focusView.id== R.id.cl_touping||focusView.id== R.id.cl_file){viewPager.currentItem=0}else if(focusView.id==R.id.cl_whiteboard){viewPager.currentItem=1}if(viewPager.currentItem==2){Log.d(TAG,"homeRightFragment.centerAppAdapter.focusPos  focusPos:${homeRightFragment.centerAppAdapter.focusPos}")//  if(homeRightFragment.centerAppAdapter.focusPos%8==0){if((homeRightFragment.centerAppAdapter.focusPos)%8==0){viewPager.currentItem=1}Log.d(TAG," 當前是在 vp currentItem =2 下")try {val rightAppInfo: RightAppInfo? = viewModel.rightAppInfoLiveData.valueLog.d(TAG,"   rightAppInfo:${Gson().toJson(rightAppInfo)}")rightAppInfo?.let { it->if( it.index%8==0){viewPager.currentItem=1}}} catch (e: Exception) {e.printStackTrace()}}} else if(resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {if(focusView.id== R.id.cl_clock||focusView.id== R.id.cl_touping||focusView.id== R.id.cl_bizhi||focusView.id== R.id.cl_googleplay||focusView.id== R.id.cl_file){viewPager.currentItem=0}else if(focusView.id==R.id.cl_whiteboard){viewPager.currentItem=1}if(viewPager.currentItem==2){Log.d(TAG,"homeRightFragment.centerAppAdapter.focusPos  focusPos:${homeRightFragment.centerAppAdapter.focusPos}")//  if(homeRightFragment.centerAppAdapter.focusPos%4==0){if((homeRightFragment.centerAppAdapter.focusPos)%4==0){viewPager.currentItem=1}Log.d(TAG," 當前是在 vp currentItem =2 下")try {val rightAppInfo: RightAppInfo? = viewModel.rightAppInfoLiveData.valueLog.d(TAG,"   rightAppInfo:${Gson().toJson(rightAppInfo)}")rightAppInfo?.let { it->if( it.index%4==0){viewPager.currentItem=1}}} catch (e: Exception) {e.printStackTrace()}}}}}KeyEvent.KEYCODE_DPAD_RIGHT -> {Log.d(TAG," KEYCODE_DPAD_RIGHT  ")val rootview = window.decorViewval focusView = rootview.findFocus()Log.i(TAG, "===當前獲取焦點的View===${focusView}")focusView?.let {if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {if(focusView.id== R.id.cl_homeleft_second){viewPager.currentItem=1}else if(focusView.id== R.id.cl_home_listapp||focusView.id== R.id.cl_touping||focusView.id== R.id.cl_music){viewPager.currentItem=2}} else if(resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {if(focusView.id== R.id.cl_homeleft_second||focusView.id== R.id.cl_homeleft_center||focusView.id== R.id.cl_homeleft_first ){viewPager.currentItem=1}else if(focusView.id== R.id.cl_home_listapp||focusView.id== R.id.cl_music||focusView.id== R.id.cl_touping||focusView.id== R.id.cl_home_healsound){viewPager.currentItem=2}}if(viewPager.currentItem==1){Log.d(TAG," 當前是在 vp currentItem =1 下")try {val centerShutIndexInfo: CenterShutIndexInfo? = viewModel.centerShutIndexInfoLiveData.valueLog.d(TAG,"   centerShutIndexInfo:${Gson().toJson(centerShutIndexInfo)}")centerShutIndexInfo?.let { it->if((it.index+1)==it.totalNum){viewPager.currentItem=2}}} catch (e: Exception) {e.printStackTrace()}}}}}return super.onKeyDown(keyCode, event)}

獲取當前焦點

在開發遙控器控制過程中,最重要的就是知道當前焦點是哪里,這樣才能分析各種不可變的bug,只有找到了焦點的位置,針對性解決焦點問題。

這里監聽窗體的焦點事件,在監聽KeyEvent 事件響應地方也有相關代碼的。

     window.decorView.findFocus()?.let { focusedView ->Log.d(TAG, "decorView 焦點 View 信息: 類名: ${focusedView.javaClass.name}")}

四、實際開發技能分享

假使你已經具備了上面的基礎知識,實際在項目項目中還是會被焦點問題搞得焦頭爛額、無從下手,遇到問題針對性解決。 這里給出自己的部分經驗。

處理焦點注意實現

  • 需要獲取焦點UI組件,設置為android:focusable=“true” , 不需要獲取焦點的組件設置為 false
  • 給每個界面顯示的時候設置初始化焦點,如上 onResume 方法中,給對應的UI組件 requestFocus() 一次
  • 給組件設置holder.vb.root.setOnFocusChangeListener 監聽事件,有焦點和無焦點情緒下顯示不同效果。
  • 監聽onKeyDown 事件,結合自己的軟件業務,實現不同的業務需求。
  • 注意在邊角的UI組件,RecycleView 的部分情形下,針對UI指定 上下左右焦點,保持焦點不外溢、丟失。
  • 對Banner 類型UI組件,自己根據實際問題來解決,因為Banner 會輪訓圖片、視頻 等導致焦點錯亂丟失情況,可以具體問題具體分析
  • RecycleView 對于邊角問題處理,對于行位、行首、豎方向收尾、豎方向最后一位的焦點處理。 下面會具體分析。

RecycleView 案例分析

RecycleView 會有兩種情況特別注意

  • 比如你的RecycleView 焦點在四周,恰好是左邊、右邊、上邊、下邊 需要攔截,如果不攔截的話焦點丟失不見了
  • 需要判斷RecycleView 焦點是否在四周哪個方向,做對應的業務邏輯處理。比如網格布局情況下,在最左邊情形下需要翻頁、在最右要攔截、最下邊要攔截。

情形一:網格布局情況下,橫屏豎屏顯示情況下,判斷焦點是否在最左邊,如果最左邊就用viewPager 翻頁處理
在這里插入圖片描述
在這里插入圖片描述

情形而:如下判斷是否邊角焦點,處理對應業務,比如底部不讓事件傳遞,焦點定在那里,不然會失去焦點。

   private fun handleLightViewTopBoundary(): Boolean {// 可以轉移到其他View或保持焦點val first: View = viewBinding.lightRyView.getChildAt(0)if (first != null) {first.requestFocus()return true}return false}private fun handleLightViewRightBoundary(position: Int): Boolean {// 類似處理右邊邊界//  val lastPos: Int = viewBinding.lightRyView.getAdapter()!!.getItemCount() - 1val last: View =viewBinding.lightRyView.findViewHolderForAdapterPosition(position)!!.itemViewif (last != null) {last.requestFocus()return true}return false}private fun handleLightViewLeftBoundary(position: Int): Boolean {// 類似處理左邊邊界// val lastPos: Int = viewBinding.lightRyView.getAdapter()!!.getItemCount() - 1val last: View =viewBinding.lightRyView.findViewHolderForAdapterPosition(position)!!.itemViewif (last != null) {last.requestFocus()return true}return false}private fun handleLightViewBottomBoundary(): Boolean {// 類似處理底部邊界val lastPos: Int = viewBinding.lightRyView.getAdapter()!!.getItemCount() - 1val last: View =viewBinding.lightRyView.findViewHolderForAdapterPosition(lastPos)!!.itemViewif (last != null) {last.requestFocus()return true}return false}

如下:如果是底部最后一行了,那么就不讓事件傳遞,這樣就不會丟失焦點。 在上下左右焦點都是這么處理的,就是判斷 或者 在邊焦點時候做其他業務處理。

在這里插入圖片描述

總結

  • 遙控器功能開發,本身就是處理焦點的問題,這里簡要描述了焦點基本知識、實際開發案例、注意事項。
  • 簡單的UI焦點處理事件很簡單的,默認就支持,可能需要定制焦點選中UI
  • 對于RecycleView 、banner 嵌套在Fragmetn / Dialog 或者 自嵌套 的復雜UI情形,焦點很容易沒有規律,掌握一些基本的處理方案很重要。 遇到問題針對性解決即可。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/85331.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/85331.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/85331.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

《HTTP權威指南》 第3章 HTTP報文

報文是如何流動的 HTTP報文是在HTTP程序之間發送的數據塊。數據塊以一些文本形式的元信息開頭。 報文方向有&#xff1a;流入、流出、上游、下游。 流入和流出描述事務處理的方向&#xff0c;流入和流出是基于服務器的描述。 流入&#xff1a;客戶端發往服務器的請求報文 流…

Kafka 集群架構與高可用方案設計(二)

Kafka 集群架構與高可用方案的優化策略 合理配置參數 在 Kafka 集群的配置中&#xff0c;參數的合理設置對于系統的高可用性和性能表現起著關鍵作用。例如&#xff0c;min.insync.replicas參數定義了 ISR&#xff08;In-Sync Replicas&#xff0c;同步副本&#xff09;集合中…

47-Oracle ASH報告解讀

上一期生成了ASH報告后&#xff0c;就需要解讀報告關鍵信息。ASH的使用可以快速定位瞬時性能問題。生產環境的場景時間緊、任務重&#xff0c;但是必須要結合具體業務分析&#xff0c;同時借助其他工具做報告做趨勢分析。 一、ASH 技術原理? ?1. 核心機制? ?采樣原理?&a…

“本地化思維+模塊化體驗”:一款輕量數據中心監控系統的真實測評

“本地化思維模塊化體驗”&#xff1a;一款輕量數據中心監控系統的真實測評 在數據中心運維逐步精細化的今天&#xff0c;一款真正貼合本地用戶習慣、設計有溫度的系統并不多見。近期體驗了一款功能全面、邏輯清晰的監控平臺&#xff0c;給人留下了深刻印象。并不是廣。今天就從…

詞編碼模型有哪些

詞編碼模型有哪些 詞編碼模型在高維向量空間的關系解析與實例說明 如Word2Vec、BERT、Qwen等 一、高維向量空間的基礎概念 詞編碼模型(如Word2Vec、BERT、Qwen等)的核心是將自然語言符號映射為稠密的高維向量,使語義相近的詞匯在向量空間中位置接近。以Qwen模型為例,其…

elementui el-select 獲取value和label 以及 對象的方法

獲取 el-select 的 value 和 label 值 在 Element UI 的 el-select 組件中&#xff0c;可以通過以下方法獲取選項的 value 和 label 值。 1、綁定 v-model 獲取 value el-select 通常通過 v-model 綁定 value 值&#xff0c;直接訪問綁定的變量即可獲取當前選中的 value。…

樹莓派與嵌入式系統實驗報告

一、Linux 系統編譯工具鏈實踐&#xff1a;mininim 源碼編譯 虛擬機 Ubuntu 編譯流程 環境配置問題 編譯時遇到虛擬機無法聯網的情況&#xff0c;通過連接個人熱點解決&#xff08;校園網限制導致無法訪問外部資源&#xff09;。 執行 ./bootstrap 時報錯 gnulib-tool: command…

IDEA部署redis測試

新建springboot&#xff0c;項目改為&#xff1a;testredis E:\ideaproject\testredis\src\main\java\org\example\testredis\TestredisApplication.java 代碼為&#xff1a; package org.example.testredis;import org.springframework.boot.SpringApplication; import org.…

旅游服務禮儀實訓室:從歷史演進到未來創新的實踐探索

一、旅游服務禮儀實訓室的歷史演進&#xff1a;從禮制規范到職業化培養 旅游服務禮儀實訓室的建設并非一蹴而就&#xff0c;其發展歷程與人類對禮儀認知的深化及職業教育體系的完善密切相關。 1. 古代禮儀教育的萌芽 禮儀作為社會行為規范&#xff0c;最早可追溯至中國夏商周…

Could not find a declaration file for module ‘..XX‘.

1. 添加 Vue 聲明文件 如果您還沒有為 .vue 文件創建類型聲明&#xff0c;可以通過創建一個新的類型聲明文件來解決該問題。 步驟&#xff1a; 在您的項目根目錄下創建一個名為 shims-vue.d.ts 的文件&#xff08;您可以選擇其他名稱&#xff0c;但建議使用常見名稱以便于識…

OpenCV CUDA模塊設備層-----反正切(arctangent)函數atan()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 對輸入的 uchar1 像素值&#xff08;范圍 [0, 255]&#xff09;&#xff0c;先歸一化到 [0.0, 1.0] 浮點區間&#xff0c;然后計算其反正切值 at…

java中常見的排序算法設計介紹

排序算法 復雜度原地排序冒泡排序算法邏輯時間復雜度&#xff1a;最好O(n)&#xff0c;最壞和平均O(n^2)冒泡排序:穩定性算法 選擇排序算法邏輯時間復雜度&#xff1a;最好&#xff0c;最壞和平均都是O(n^2)選擇排序:不穩定性算法 插入排序算法邏輯時間復雜度&#xff1a;最好O…

深度學習系列81:MCP快速上手

MCP 是一種開放協議&#xff0c;通過標準化的服務器實現&#xff0c;使 AI 模型能夠安全地與本地和遠程資源進行交互。MCP 可幫助你在 LLM 之上構建智能代理和復雜的工作流。MCP 采用客戶端-服務器架構&#xff0c;主機應用程序可以連接到多個服務器。 這里用個demo展示一下如何…

【Python機器學習(一)】NumPy/Pandas手搓決策樹+使用Graphviz可視化(以西瓜書數據集為例)

下題來源于筆者學校的《模式識別與機器學習》課程的作業題,本文將通過使用NumPy處理數學運算,Pandas處理數據集,Graphviz實現決策樹可視化等Python庫來實現決策樹算法及其格式化。 導入用到的Python庫: import numpy as np import pandas as pd from graphviz import Digr…

react-activation 組件級緩存解決方案

文章目錄 一、KeepAlive 組件二、AliveScope 容器三、useAliveController Hook四、生命周期五、完整示例 react-activation 主要解決 React 項目中的「頁面緩存」需求(是第三方庫&#xff0c;非React 官方)&#xff0c;類似于 Vue 中的 <KeepAlive>&#xff1a; 功能說明…

CentOS 7內核升級方案

關于升級 CentOS 7 系統內核至 4.19 版本的可執行升級方案,可根據實際情況進行調整和完善,希望能對大家有所幫助: 一、升級背景與目的 隨著業務的發展和系統穩定性的要求,當前 CentOS 7 系統所使用的內核版本 3.10.0-1160.el7.x86_64 已經無法滿足部分新功能需求以及面臨…

樹莓派實驗實踐記錄與技術分析

一、內核驅動開發&#xff1a;hello 模塊實現 驅動程序代碼 #include <linux/init.h> #include <linux/module.h> static int __init hello_init(void) { printk(KERN_INFO "hello kernel\n"); return 0; } module_init(hello_init); static void …

【秦九紹算法】小紅的 gcd

題目 牛客網&#xff1a;小紅的 gcd 題目分析 我們知道&#xff0c;求gcd就用歐幾里得算法&#xff08;輾轉相除法&#xff09;&#xff1a;gcd(a,b)gcd(b,a mod b)。但是這題的a非常大&#xff0c;最大是一個1e6位數&#xff0c;無法使用任何數據類型存儲。如果使用高精度…

AWS服務監控之EC2內存監控

首先在IAM里找到角色&#xff0c;創建角色&#xff0c;選擇EC2 然后在被監控的機器上安裝cloudwatch-agent 官方鏈接在本地服務器上安裝 CloudWatch 代理 - Amazon CloudWatch wget https://s3.amazonaws.com/amazoncloudwatch-agent/redhat/amd64/latest/amazon-cloudwatch-a…

鴻蒙 ArkWeb 和 H5混編開發

ArkWeb Web 相關標準技術(HTML/CSS/JS)&#xff0c;是業內支持性最廣泛的技術&#xff0c;可以在最廣泛的平臺下實現“一次編寫到處運行”&#xff1b;大部分對性能無需極致要求的應用頁面&#xff0c;都可以使用 Web 技術來實現。 鴻蒙 ArkWeb Kit&#xff08;方舟 Web&…