首页 > 解决方案 > React Native Expo 开启和关闭音频

问题描述

我想在我的 react native expo 应用程序中打开和关闭声音,但是当我多次打开和关闭时,它会导致声音重叠并且我不确定是否需要设置音频状态?我似乎在这里找不到任何好的例子 - https://docs.expo.io/versions/latest/sdk/av/不确定我做错了什么,RN的新手。

如您所见,这是一个标题按钮,它必须在整个应用程序中工作,而不仅仅是一个屏幕。

这是我的零食 - https://snack.expo.io/@roshambo/sound-toggle-on-and-off

import React, { useState } from "react";
import { HeaderButton } from "react-navigation-header-buttons";
import { Ionicons } from "@expo/vector-icons";
import { Audio } from "expo-av";

const CustomHeaderButton = props => {
const [soundIcon, setSoundIcon] = useState(false);

const soundObject = new Audio.Sound();
(async () => {
  await soundObject.loadAsync(require("../assets/bglaughs.mp3"), {
    volume: 0.25,
    isLooping: true,
    shouldPlay: true,
    isMuted: true
  });
})();

const toggleSound = () => {
  setSoundIcon(prevState => !prevState);
  soundObject.setOnPlaybackStatusUpdate(this._onPlaybackStatusUpdate);
};

_onPlaybackStatusUpdate = playbackStatus => {
  if (playbackStatus.isMuted) {
    playSound();
  } else {
    stopSound();
  }
};

const stopSound = async () => {
  try {
    await soundObject.stopAsync();
  } catch (error) {
    console.log("sound couldn't pause");
  }
};

const playSound = async () => {
  try {
    await soundObject.setIsMutedAsync(false);
    await soundObject.playAsync();
  } catch (error) {
    console.log("sound couldn't play");
  }  
};

return (
<HeaderButton
  {...props}
  IconComponent={Ionicons}
  iconSize={23}
  iconName={soundIcon ? "ios-volume-high" : "ios-volume-off"}
  onPress={toggleSound}
  />
  );
};

export default CustomHeaderButton;

更新:

这是我基于 Oleg 的回答的工作代码以及我在 redux 上的实现。

零件

import React from "react";
import { HeaderButton } from "react-navigation-header-buttons";
import { useDispatch, useSelector } from "react-redux";

import * as soundActions from "../store/actions/sound-action";

import { Ionicons } from "@expo/vector-icons";

const CustomHeaderButton = props => {

  const sound = useSelector(state => state.sound.soundState);

  const dispatch = useDispatch();

  return (
    <HeaderButton
      {...props}
      IconComponent={Ionicons}
      iconSize={23}
      iconName={sound === "playing" ? "ios-volume-high" : "ios-volume-off"}
      onPress={() => {
        dispatch(soundActions.toggleSound(sound));
      }}
    />
  );
};

export default CustomHeaderButton;

减速器

import { TOGGLE_SOUND } from "../actions/sound-action";

import { Audio } from "expo-av";

const initialState = {
  soundState: "nosound"
};

export default (state = initialState, action) => {
  switch (action.type) {
    case TOGGLE_SOUND:
      if (state.soundState === "nosound") {
        (async () => {
          const { sound } = await Audio.Sound.createAsync(
            require("../../assets/bglaughs.mp3"),
            {
              shouldPlay: true,
              volume: 0.25,
              isLooping: true
            }
          );
          this.sound = sound;
        })();
        return {
          ...state,
          soundState: "playing"
        };
      } else if (state.soundState === "playing") {
        (async () => {
          if (this.sound !== null) {
            await this.sound.pauseAsync();
          }
        })();
        return { ...state, soundState: "donepause" };
      } else if (state.soundState === "donepause") {
        (async () => {
          await this.sound.playAsync();
        })();
        return { soundState: "playing" };
      }
  }
  return state;
};

标签: react-nativeexpo

解决方案


我为您的问题创建了零食答案:您必须注意创建声音和标志循环设置为 false 的新方法。

https://snack.expo.io/@djalik/sound-toggle-on-and-off


推荐阅读