Hoje, apresento um tutorial sobre o desenvolvimento de um aplicativo de filmes utilizando o HarmonyOS Next. Este projeto envolve a criação de interfaces simples, reprodução de vídeos locais e suporte a rotação entre modo retrato e paisagem.
Começaremos pela página inicial do aplicativo, que é uma lista com seções que podem ser roladas horizontalmente. A parte superior, um banner rotativo, é implementada usando o componente Swiper. As outras seções utilizam o componente Scroll. O código relevante segue abaixo:
build() {
List() {
ListItem() {
Swiper() {
Image($r('app.media.headimg'))
.width('100%')
.height(380)
.objectFit(ImageFit.Fill)
.onClick(() => {
router.pushUrl({
url: 'pages/Detalhes'
})
})
}
}
ListItemGroup({ header: this.cabecalhoLista('Categorias', false) }) {
ListItem() {
Scroll() {
Row() {
ForEach(this.tipos, (categoria: string, indice: number) => {
Text(categoria)
.fontSize(15)
.fontColor(Color.Branco)
.padding({ top: 8, bottom: 8, left: 22, right: 22 })
.borderRadius(15)
.backgroundColor(this.tipoAtual == indice ? '#6152FF' : 'rgb(6,4,31)')
.onClick(() => {
router.pushUrl({
url: 'pages/ListagemFilmes'
})
})
})
}
}
.scrollable(ScrollDirection.Horizontal)
.scrollBar(BarState.Off)
.width('100%')
}
}
.padding({ left: 12, right: 12 })
ListItemGroup({ header: this.cabecalhoLista('Mais Populares', true) }) {
ListItem() {
Scroll() {
Row({ space: 10 }) {
ForEach(this.filmesPopulares, (imagem: Resource, indice: number) => {
Image(imagem)
.width(124)
.height(180)
.objectFit(ImageFit.Contain)
.borderRadius(10)
.onClick(() => {
router.pushUrl({
url: 'pages/Detalhes'
})
})
})
}
}
.scrollable(ScrollDirection.Horizontal)
.scrollBar(BarState.Off)
.width('100%')
}
}
.padding({ left: 12, right: 12 })
ListItemGroup({ header: this.cabecalhoLista('Últimos Lançamentos', true) }) {
ListItem() {
Scroll() {
Row({ space: 10 }) {
ForEach(this.filmesPopulares, (imagem: Resource, indice: number) => {
Image(imagem)
.width(124)
.height(180)
.objectFit(ImageFit.Contain)
.borderRadius(10)
.onClick(() => {
router.pushUrl({
url: 'pages/Detalhes'
})
})
})
}
}
.scrollable(ScrollDirection.Horizontal)
.scrollBar(BarState.Off)
.width('100%')
}
}
.padding({ left: 12, right: 12 })
}
.width('100%')
.height('100%')
.backgroundColor('rgb(6,4,31)')
}
@Builder cabecalhoLista(titulo: string, exibirTodos: boolean) {
Row() {
Text(titulo)
.fontColor(Color.Branco)
.fontSize(15)
if (exibirTodos) {
Text('Ver Todos')
.fontColor(Color.Branco)
.fontSize(11)
}
}
.alignItems(VerticalAlign.Center)
.width('100%')
.height(40)
.justifyContent(FlexAlign.SpaceBetween)
.onClick(() => {
router.pushUrl({
url: 'pages/ListagemFilmes'
})
})
}
Agora, vamos para a parte de manipulação de vídeo. Para isso, colocamos o arquivo de vídeo na pasta rawfile e usamos o componente Video para sua reprodução:
Video({
src: $rawfile('filme.mp4'),
controller: this.controleVideo
})
.width('100%')
.height(this.emModoPaisagem ? '100%' : this.larguraTela * 9 / 16)
.autoPlay(true)
.controls(false)
.objectFit(ImageFit.Cover)
.loop(false)
O componente Video oferece controles de toolbar e opção de tela cheia, mas geralmente não são suficientes para aplicações reais. Por isso, criamos nossa própria barra de controle e manipulamos a mudança de orientação alterando as dimensões do componente.
Para mudar a orientação para paisagem, escondemos a barra de status e a barra de navegação e, em seguida, definimos a orientação da janela como paisagem. Veja o código abaixo:
alterarOrientacao() {
// Obtém o contexto da UIAbility
let contexto = getContext(this);
// Altera manualmente a orientação do dispositivo
window.getLastWindow(contexto).then((ultimaJanela) => {
if (this.emModoPaisagem) {
ultimaJanela.setWindowLayoutFullScreen(true).then(() => {
ultimaJanela.setWindowSystemBarEnable([]);
ultimaJanela.setPreferredOrientation(window.Orientation.AUTO_ROTATION_LANDSCAPE, () => {
this.modoPaisagem = !this.modoPaisagem;
});
});
}
});
}
A saída do modo tela cheia é feita inevrtendo as operações acima.