上一期把DAYU200的开发板系统升级成了OpenHarmony3.1 Release 版,
这一期和大家分享,基于eTS 开发一个管家服务系统,其实设想是用DAYU200上实现全屋智能中控系统,也设想了一些功能,东西有点多,
先实现管家服务系统的两个UI效果:语音助手、提醒服务。
这一期实践了以下内容:
swiper组件、//切换多组页面的组件
Panel组件、//可以从底部弹出/收回/滑动的面板组件
@Builder、 //生成布局,可以方便的传递参数
import router from ‘@system.router’; //导入router用于跳转页面的系统组件
import { voiceAssistant } from ‘./voice_assistant’//导入自定义组件
export //作为组件库库导出
------------开发环境-------------------
DevEco Studio 3.0 Beta3
Build Version: 3.0.0.900, built on March 30, 2022
SDK:API Version 8
1、效果
2、界面代码
(1) 首页
import router from '@system.router';
import { HomeData, initHomeData } from '../pages/model/HomeDataModel'
@Entry
@Component
struct Index {
@State data: HomeData = initHomeData()
@State panelShow: boolean= false
private swiperController: SwiperController = new SwiperController()
build() {
Stack({ alignContent: Alignment.Bottom }) {
this.buildTopBar()
this.buildSwiper()
this.buildPanel()
}
.height('100%')
.backgroundColor(Color.Black)
}
@Builder buildTopBar() {
//panel bar
Column() {
Column() {
Image($r('app.media.slide'))
.objectFit(ImageFit.Contain)
.height(50)
}
.height(50)
.opacity(0.9)
.backgroundColor('#1F71FF')
.onClick(() => {
this.panelShow = !this.panelShow
})
}.height('100%')
}
@Builder buildSwiper() {
//swiper
Column({ space: 5 }) {
Swiper(this.swiperController) {
//首页
this.builderPageHome()
//其它
this.builderPageOther()
}
.index(0)
.autoPlay(false)
.interval(4000)
.indicator(true) // 默认开启指示点
.loop(false) // 默认开启循环播放
.duration(1000)
.vertical(false) // 默认横向切换
.itemSpace(0)
.onChange((index: number) => {
console.info(index.toString())
})
}
//.backgroundColor(Color.Blue)
}
@Builder builderPageHome() {
//middle range
Column() {
//date time
Row() {
Column() {
//time/date
Text(this.data.time)
.fontSize(80)
.fontWeight(FontWeight.Bolder)
.fontColor(Color.White)
//.backgroundColor(Color.Pink)
Text(this.data.date + " " + this.data.week)
.fontSize(40)
.fontWeight(FontWeight.Bold)
.fontColor(Color.White)
//.backgroundColor(Color.Yellow)
}.width('100%')
}
.width('100%')
//.backgroundColor(Color.Brown)
//weather info
Row() {
Column() {
if (this.data.weather === 'cloud2sun') {
Image($r("app.media.weather_cloud2sun"))
.objectFit(ImageFit.Contain)
.width('120')
.height('120')
}
else if (this.data.weather === 'sun') {
Image($r("app.media.weather_cloud2sun"))
.objectFit(ImageFit.Contain)
.width('120')
.height('120')
}
Text(this.data.temperature)
.fontSize(40)
.fontWeight(FontWeight.Bold)
.fontColor(Color.White)
.textAlign(TextAlign.Center)
}
//.backgroundColor(Color.Blue)
}
//operation button
Row() {
Column() {
Button() {
Text('语音助手')
.fontColor(Color.White)
.textAlign(TextAlign.Center)
.fontWeight(FontWeight.Bold)
.fontSize(25)
.width('100%')
}
.type(ButtonType.Normal)
.borderRadius(15)
.height('150')
.width('90%')
.opacity(0.9)
.alignSelf(ItemAlign.Center)
.onClick(() => {
router.push({ uri: 'pages/voice_assistant', params: {
switchMode: 'homeMode'
} })
})
}
.layoutWeight(1)
Column() {
Button() {
Text('提醒服务')
.fontColor(Color.White)
.textAlign(TextAlign.Center)
.fontWeight(FontWeight.Bold)
.fontSize(25)
.width('100%')
}
.type(ButtonType.Normal)
.borderRadius(15)
.height('150')
.width('90%')
.opacity(0.9)
.alignSelf(ItemAlign.Center)
.onClick(() => {
router.push({ uri: 'pages/bssm' })
})
}
.layoutWeight(1)
}
.padding(30)
//.backgroundColor(Color.Grey)
}
.margin({ top: 52 })
.height('90%')
}
@Builder builderPageOther() {
Column() {
Text('welcome to you')
.fontColor(Color.White)
.fontSize(30)
.width('100%')
.height('100%')
.textAlign(TextAlign.Center)
.backgroundColor(Color.Black)
}
.height('90%')
.margin({ top: 52 })
}
@Builder buildPanel() {
//button panel
Panel(this.panelShow) {
Column() {
//first line
Row() {
Column() {
Image($r('app.media.home'))
.objectFit(ImageFit.Contain)
.width('50').height('50')
Text('彩光')
.fontColor(Color.White)
.textAlign(TextAlign.Center)
.fontWeight(FontWeight.Bold)
.fontSize(25)
.width('50%')
}
.layoutWeight(1)
.borderRadius(15)
.width('20%')
.padding(10)
.opacity(0.9)
.onClick(() => {
router.push({ uri: 'pages/lanls_colorful' })
})
.backgroundColor(Color.Gray)
Column() {
Image($r('app.media.setting'))
.objectFit(ImageFit.Contain)
.width('50').height('50')
Text('白光')
.fontColor(Color.White)
.textAlign(TextAlign.Center)
.fontWeight(FontWeight.Bold)
.fontSize(25)
.width('50%')
}
.layoutWeight(1)
.borderRadius(15)
.width('20%')
.padding(10)
.opacity(0.9)
.onClick(() => {
router.push({ uri: 'pages/lanls_lighting' })
})
.backgroundColor(Color.Gray)
Column() {
Image($r('app.media.screen'))
.objectFit(ImageFit.Contain)
.width('50').height('50')
Text('语音管家')
.fontColor(Color.White)
.textAlign(TextAlign.Center)
.fontWeight(FontWeight.Bold)
.fontSize(25)
.width('100%')
}
.layoutWeight(1)
.borderRadius(15)
.width('20%')
.padding(10)
.opacity(0.9)
.onClick(() => {
console.log("------------route")
router.push({ uri: 'pages/voice_assistant' })
})
.backgroundColor(Color.Gray)
}
//second line
Row() {
Column() {
Image($r('app.media.sync'))
.objectFit(ImageFit.Contain)
.width('50').height('50')
Text('场景')
.fontColor(Color.White)
.textAlign(TextAlign.Center)
.fontWeight(FontWeight.Bold)
.fontSize(25)
.width('50%')
}
.layoutWeight(1)
.borderRadius(15)
.width('20%')
.padding(10)
.opacity(0.9)
.onClick(() => {
router.push({ uri: 'pages/lanls_scenes' })
})
.backgroundColor(Color.Gray)
Column() {
Image($r('app.media.sensor'))
.objectFit(ImageFit.Contain)
.width('50').height('50')
Text('通知')
.fontColor(Color.White)
.textAlign(TextAlign.Center)
.fontWeight(FontWeight.Bold)
.fontSize(25)
.width('50%')
}
.layoutWeight(1)
.borderRadius(15)
.width('20%')
.padding(10)
.opacity(0.9)
.onClick(() => {
router.push({ uri: 'pages/bssm' })
})
.backgroundColor(Color.Gray)
Column() {
Image($r('app.media.theme'))
.objectFit(ImageFit.Contain)
.width('50').height('50')
Text('主题')
.fontColor(Color.White)
.textAlign(TextAlign.Center)
.fontWeight(FontWeight.Bold)
.fontSize(25)
.width('50%')
}
.layoutWeight(1)
.borderRadius(15)
.width('20%')
.padding(10)
.onClick(() => {
router.push({ uri: 'pages/index' })
})
.backgroundColor(Color.Gray)
}
}
.height('100%')
}
.type(PanelType.Foldable)
.mode(PanelMode.Half)
.halfHeight(500)
.dragBar(true) // 默认开启
.onChange((value: any) => {
console.info(`width:${value.width},height:${value.height},mode:${value.mode}`)
})
.height('90%')
.backgroundColor(Color.Gray)
}
}
(2) 语音助手
voice_assistant.ets
@Entry
@Component
struct voiceAssistant {
@State listening: boolean= false
@State answer: string= '您好,有什么吩咐!'
private listeningWord: string= '我正在聆听..'
private doneWord: string= '好的,已经帮您打开'
build() {
Column() {
Row() {
Image($r('app.media.ready'))
.objectFit(ImageFit.Contain)
.height('100%')
.width('100%')
}
.alignItems(VerticalAlign.Bottom)
.height('60%')
//.backgroundColor(Color.Red)
.onClick(() => {
if (this.listening) {
this.answer = this.doneWord
this.listening = false
} else {
this.answer = this.listeningWord;
this.listening = true
}
})
Row() {
Text(this.answer)
.fontSize('35')
.fontColor(Color.White)
.textAlign(TextAlign.Center)
.width('100%')
.padding(10)
}
.height('40%')
//.backgroundColor(Color.Gray)
}
.backgroundColor(Color.Black)
}
}
(3) 提醒服务
smart_reminder.ets
import router from '@system.router';
@Entry
@Component
struct bssm {
@State notice:string='快递已经到家,快到门口去拿!\n'
build() {
Column() {
this.buildNotice()
}
.height('100%')
.backgroundColor(Color.Black)
}
@Builder buildNotice() {
Column() {
Column() {
//image
Row() {
Image($r('app.media.img_6'))
//.width('20%')
//.height('20%')
.objectFit(ImageFit.Contain)
.width('100%')
.height('70%')
.margin('2%')
}
.height('45%')
//.backgroundColor(Color.Red)
//date
Row() {
Text('19:32 04/20')
.fontSize('25')
.fontColor(Color.White)
.textAlign(TextAlign.Center)
.width('100%')
}
.height('10%')
//.backgroundColor(Color.Green)
//notice
Row() {
Text(this.notice)
.fontSize('25')
.fontColor(Color.White)
.textAlign(TextAlign.Center)
.textOverflow({overflow:TextOverflow.Ellipsis})//超长省略号代替
.maxLines(3)
.padding('2%')
.width('100%')
}
.height('20%')
//.backgroundColor(Color.Red)
}
.width('95%')
.margin({ top: '3%' })
.borderRadius(10)
.backgroundColor('#2c3134')
Row() {
Button() {
Text('好的').fontSize(20).fontColor(Color.White)
}
.type(ButtonType.Normal)
.borderRadius(5)
.height('70%')
.width('100%')
.onClick(() => {
router.push({ uri: 'pages/index' })
})
}
.margin('1%')
.width('95%')
.height('15%')
//.backgroundColor(Color.Pink)
}
.height('100%')
.width('100%')
.borderRadius(10)
.alignItems(HorizontalAlign.Center)
.backgroundColor(Color.Black)
}
}
3、总结
- eTS声明式的语法用着还是挺舒服的,调试布局可以通过设定组件的backgroundColor来验证。
- 后续根据自己的想法再慢慢加一些功能进去,比如结合一些AI能力进去,还有消息通知效果策略等,随便发挥把。