Tutorial de Desenvolvimento de Aplicativo de Vídeos com HarmonyOS Next

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.

Tags: HarmonyOS Next DesenvolvimentoMobile VídeoPlayback InterfaceResponsiva

Publicado em 8-20 01:13