概述
目前家庭電視機(jī)主要通過其自帶的遙控器進(jìn)行操控,實(shí)現(xiàn)的功能較為單一。例如,當(dāng)我們要在TV端搜索節(jié)目時(shí),電視機(jī)在遙控器的操控下往往只能完成一些字母或數(shù)字的輸入,而無法輸入其他復(fù)雜的內(nèi)容。分布式遙控器將手機(jī)的輸入能力和電視遙控器的遙控能力結(jié)合為一體,從而快速便捷操控電視。
分布式遙控器的實(shí)現(xiàn)基于OpenHarmony的分布式能力和RPC通信能力,UI使用eTS進(jìn)行開發(fā)。如下圖所示,分別用兩塊開發(fā)板模擬TV端和手機(jī)端。
分布式組網(wǎng)后可以通過TV端界面的Controller按鈕手動(dòng)拉起手機(jī)端的遙控界面,在手機(jī)端輸入時(shí)會(huì)將輸入的內(nèi)容同步顯示在TV端搜索框,點(diǎn)擊搜索按鈕會(huì)根據(jù)輸入的內(nèi)容搜索相關(guān)節(jié)目。
還可以通過點(diǎn)擊方向鍵(上下左右)將焦點(diǎn)移動(dòng)到我們想要的節(jié)目上,再點(diǎn)擊播放按鈕進(jìn)行播放,按返回按鈕返回TV端主界面。
同時(shí)還可以通過手機(jī)遙控端關(guān)機(jī)按鈕同時(shí)關(guān)閉TV端和手機(jī)端界面。
實(shí)現(xiàn)TV端界面
在本章節(jié)中,您將學(xué)會(huì)開發(fā)TV端默認(rèn)界面和TV端視頻播放界面,示意圖參考第一章圖1和圖3所示。
建立數(shù)據(jù)模型,將圖片ID、圖片源、圖片名稱和視頻源綁定成一個(gè)數(shù)據(jù)模型。詳情代碼可以查看MainAbility/model/PicData.ets和MainAbility/model/PicDataModel.ets兩個(gè)文件。
實(shí)現(xiàn)TV端默認(rèn)頁面布局和樣式,在MainAbility/pages/TVIndex.ets 主界面文件中添加入口組件。頁面布局代碼如下:
// 入口組件
@Entry
@Component
struct Index {
private letters: string[] = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
private source: string
@State text: string = ''
@State choose: number = -1
build() {
Flex({ direction: FlexDirection.Column }) {
TextInput({text: this.text, placeholder: 'Search' })
.onChange((value: string) => {
this.text = value
})
Row({space: 30}) {
Text('Clear')
.fontSize(16)
.textAlign(TextAlign.Center)
.onClick(() => {
this.text = ''
})
.clip(true)
.borderRadius(10)
Text('Backspace')
.fontSize(16)
.backgroundColor('#ABB0BA')
.textAlign(TextAlign.Center)
.onClick(() => {
this.text = this.text.substring(0, this.text.length - 1)
})
.clip(true)
.borderRadius(10)
Text('Controller')
.fontSize(16)
.backgroundColor('#ABB0BA')
.textAlign(TextAlign.Center)
.onClick(() => {
......
})
.clip(true)
.borderRadius(10)
}
Grid() {
ForEach(this.letters, (item) => {
GridItem() {
Text(item)
.fontSize(20)
.backgroundColor('#FFFFFF')
.textAlign(TextAlign.Center)
.onClick(() => {
this.text += item
})
.clip(true)
.borderRadius(5)
}
}, item => item)
}
.rowsTemplate('1fr 1fr 1fr 1fr')
.columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr')
.columnsGap(8)
.rowsGap(8)
.width('75%')
.height('25%')
.margin(5)
.backgroundColor('#D2D3D8')
.clip(true)
.borderRadius(10)
Grid() {
ForEach(this.picItems, (item: PicData) => {
GridItem() {
PicGridItem({ picItem: item })
}
}, (item: PicData) => item.id.toString())
}
.rowsTemplate('1fr 1fr 1fr')
.columnsTemplate('1fr 1fr')
.columnsGap(5)
.rowsGap(8)
.width('90%')
.height('58%')
.backgroundColor('#FFFFFF')
.margin(5)
}
.width('98%')
.backgroundColor('#FFFFFF')
}
}
(左右移動(dòng)查看全部內(nèi)容)
其中PicGridItem將PicItem的圖片源和圖片名稱綁定,實(shí)現(xiàn)代碼如下:
// 九宮格拼圖組件
@Component
struct PicGridItem {
private picItem: PicData
build() {
Column() {
Image(this.picItem.image)
.height('85%')
.width('100%')
.onClick(() => {
......
})
})
Text(this.picItem.name)
.fontSize(20)
.fontColor('#000000')
}
.height('100%')
.width('90%')
}
}
(左右移動(dòng)查看全部內(nèi)容)
實(shí)現(xiàn)TV端視頻播放界面,在MainAbility/pages/VideoPlay.ets 文件中添加組件。頁面布局代碼如下:
import router from '@system.router'
@Entry
@Component
struct Play {
// 取到Index頁面跳轉(zhuǎn)來時(shí)攜帶的source對應(yīng)的數(shù)據(jù)。
private source: string = router.getParams().source
build() {
Column() {
Video({
src: this.source,
})
.width('100%')
.height('100%')
.autoPlay(true)
.controls(true)
}
}
}
(左右移動(dòng)查看全部內(nèi)容)
在MainAbility/pages/TVIndex.ets中,給PicGridItem的圖片添加點(diǎn)擊事件,點(diǎn)擊圖片即可播放PicItem的視頻源。實(shí)現(xiàn)代碼如下:
Image(this.picItem.image)
......
.onClick(() => {
router.push({
uri: 'pages/VideoPlay',
params: { source: this.picItem.video }
})
})
(左右移動(dòng)查看全部內(nèi)容)
實(shí)現(xiàn)手機(jī)遙控端界面
在本章節(jié)中,您將學(xué)會(huì)開發(fā)手機(jī)遙控端默認(rèn)界面,示意圖參考第一章圖2所示。
PhoneAbility/pages/PhoneIndex.ets 主界面文件中添加入口組件。頁面布局代碼如下:
@Entry
@Component
struct Index {
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }) {
Row() {
Image($rawfile('TV.png'))
.width(25)
.height(25)
Text('華為智慧屏').fontSize(20).margin(10)
}
// 文字搜索框
TextInput({ placeholder: 'Search' })
.margin(20)
.onChange((value: string) => {
if (connectModel.mRemote){
......
}
})
Grid() {
GridItem() {
// 向上箭頭
Button({ type: ButtonType.Circle, stateEffect: true }) {
Image($rawfile('up.png')).width(80).height(80)
}
.onClick(() => {
......
})
.width(80)
.height(80)
.backgroundColor('#FFFFFF')
}
.columnStart(1)
.columnEnd(5)
GridItem() {
// 向左箭頭
Button({ type: ButtonType.Circle, stateEffect: true }) {
Image($rawfile('left.png')).width(80).height(80)
}
.onClick(() => {
......
})
.width(80)
.height(80)
.backgroundColor('#FFFFFF')
}
GridItem() {
// 播放鍵
Button({ type: ButtonType.Circle, stateEffect: true }) {
Image($rawfile('play.png')).width(60).height(60)
}
.onClick(() => {
......
})
.width(80)
.height(80)
.backgroundColor('#FFFFFF')
}
GridItem() {
// 向右箭頭
Button({ type: ButtonType.Circle, stateEffect: true }) {
Image($rawfile('right.png')).width(70).height(70)
}
.onClick(() => {
......
})
.width(80)
.height(80)
.backgroundColor('#FFFFFF')
}
GridItem() {
// 向下箭頭
Button({ type: ButtonType.Circle, stateEffect: true }) {
Image($rawfile('down.png')).width(70).height(70)
}
.onClick(() => {
......
})
.width(80)
.height(80)
.backgroundColor('#FFFFFF')
}
.columnStart(1)
.columnEnd(5)
}
.rowsTemplate('1fr 1fr 1fr')
.columnsTemplate('1fr 1fr 1fr')
.backgroundColor('#FFFFFF')
.margin(10)
.clip(new Circle({ width: 325, height: 325 }))
.width(350)
.height(350)
Row({ space:100 }) {
// 返回鍵
Button({ type: ButtonType.Circle, stateEffect: true }) {
Image($rawfile('return.png')).width(40).height(40)
}
.onClick(() => {
......
})
.width(100)
.height(100)
.backgroundColor('#FFFFFF')
// 關(guān)機(jī)鍵
Button({ type: ButtonType.Circle, stateEffect: true }) {
Image($rawfile('off.png')).width(40).height(40)
}
.onClick(() => {
......
})
.width(100)
.height(100)
.backgroundColor('#FFFFFF')
// 搜索鍵
Button({ type: ButtonType.Circle, stateEffect: true }) {
Image($rawfile('search.png')).width(40).height(40)
}
.onClick(() => {
......
})
.width(100)
.height(100)
.backgroundColor('#FFFFFF')
}
.padding({ left:100 })
}
.backgroundColor('#E3E3E3')
}
}
(左右移動(dòng)查看全部內(nèi)容)
原文標(biāo)題:OpenHarmony 實(shí)例:DAYU200 分布式遙控器
文章出處:【微信公眾號:HarmonyOS官方合作社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
審核編輯:湯梓紅
-
遙控器
+關(guān)注
關(guān)注
18文章
840瀏覽量
66591 -
電視機(jī)
+關(guān)注
關(guān)注
7文章
398瀏覽量
44202 -
OpenHarmony
+關(guān)注
關(guān)注
25文章
3747瀏覽量
16588
原文標(biāo)題:OpenHarmony 實(shí)例:DAYU200 分布式遙控器
文章出處:【微信號:HarmonyOS_Community,微信公眾號:電子發(fā)燒友開源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
Ubuntu端的界面開發(fā)
HarmonyOS教程—基于分布式能力,將手機(jī)作為智慧屏的虛擬控制器,控制文字輸入和遙控播放
DistributedVideoPlayer分布式視頻播放器的設(shè)計(jì)資料
Linux字符界面轉(zhuǎn)圖形界面
pc端是什么意思_PC端與移動(dòng)端區(qū)別
YouTub正在為某些平臺推出經(jīng)過改進(jìn)的界面
亞馬遜新的Fire TV用戶界面即將揭曉
HarmonyOS UI界面活動(dòng)可實(shí)現(xiàn)不同屏幕的界面適配能力
如何在CubeMx配置界面將DMA中斷的默認(rèn)使能關(guān)閉
![如何在CubeMx配置<b class='flag-5'>界面</b>將DMA中斷的<b class='flag-5'>默認(rèn)</b>使能關(guān)閉](https://file1.elecfans.com/web2/M00/A2/50/wKgZomT8I0yAdxEJAAJhggHLnkU800.jpg)
【AWTK開源智能串口屏方案】設(shè)計(jì)UI界面并上傳到串口屏
![【AWTK開源智能串口屏方案】設(shè)計(jì)UI<b class='flag-5'>界面</b>并上傳到串口屏](https://file.elecfans.com/web2/M00/50/DA/pYYBAGLH6TyAB71EAAAPQ7KgtYA038.png)
評論