问题描述
我正在构建一个具有两个视图的音频播放器,一个迷你播放器(底部选项卡)和一个全屏播放器。滑动或点击以在视图之间切换。当我重新加载我的应用程序时,一切正常,我的占位符封面艺术在播放器上,我可以上下滑动。但是当我加载播放实例时,所有功能都会停止。没有滑动,没有点击。我的 onPress 仍在接收点击,但没有动作。对此有何想法?我将一些控制台日志放入 useCode 中,看起来它仅在初始加载时被调用,我认为这是有道理的。
import React,{ useState,useEffect } from 'react';
import { StyleSheet,useWindowDimensions } from 'react-native';
import MiniPlayer,{ MINI_PLAYER_HEIGHT } from './MiniPlayer';
import Animated,{
Clock,Value,cond,useCode,set,block,not,clockRunning,interpolate,Extrapolate,} from 'react-native-reanimated';
import {
clamp,timing,onGestureEvent,withSpring,} from 'react-native-redash/lib/module/v1';
import FullPlayer from './FullPlayer';
import { PanGestureHandler,State } from 'react-native-gesture-handler';
import { Audio } from 'expo-av';
import { useSelector } from '../../customHooks/useSelector';
import { audioRoute } from '../../constants/apiConfigs';
import { useStateIfMounted } from 'use-state-if-mounted';
import { usedispatch } from 'react-redux';
import { updateSleepTimer,postIsLoading } from '../../redux/media/thunks';
const springConfig = {
damping: 15,mass: 1,stiffness: 150,overshootClamping: true,restSpeedThreshold: 0.1,restdisplacementThreshold: 0.1,};
const Player = () => {
const { height } = useWindowDimensions();
const dispatch = usedispatch();
const shouldLoad =
useSelector((state) => state.media.audioInfo?.shouldLoad) || null;
const audioPost = useSelector((state) => state.media.audioInfo?.post) || null;
const storedTrackBySlug =
useSelector((state) => state.media.storedTrackBySlug) || null;
const [playbackInstance,setPlaybackInstance] = useState(null);
const [isPlaying,setIsPlaying] = useStateIfMounted(false);
const [currentPositionMillis,setCurrentPositionMillis] = useStateIfMounted(
0
);
const [totalDurationMillis,setTotalDurationMillis] = useStateIfMounted(0);
const [volume] = useStateIfMounted(1.0);
const [isBuffering,setIsBuffering] = useStateIfMounted(false);
const [rate,setRate] = useStateIfMounted(1.0);
const timerRemainingInMillis = useSelector(
(state) => state.media.audioTimer?.remainingMillis
);
const timerLastPositionInMillis = useSelector(
(state) => state.media.audioTimer?.lastPositionMillis
);
const increaseRateByQuarter = async (): Promise<void> => {
let playbackRate = rate + 0.25;
if (playbackRate > 2.0) {
playbackRate = 0.5;
}
await playbackInstance.setRateAsync(
playbackRate,true,Audio.PitchCorrectionQuality.Medium
);
};
const seekPositionBySeconds = async (position: number): Promise<void> => {
await playbackInstance.setPositionAsync(position * 1000);
if (timerRemainingInMillis > 0) {
dispatch(
updateSleepTimer(
Math.round(
(timerRemainingInMillis -
(currentPositionMillis - timerLastPositionInMillis)) /
1000
) *
1000 -
10,position * 1000
)
);
}
};
const handlePlayPause = async (): Promise<void> => {
isPlaying
? await playbackInstance.pauseAsync()
: await playbackInstance.playAsync();
setIsPlaying(!isPlaying);
};
const handleSkipBack = async (): Promise<void> => {
seekPositionBySeconds(currentPositionMillis / 1000 - 15);
};
const handleSkipForward = async (): Promise<void> => {
seekPositionBySeconds(currentPositionMillis / 1000 + 15);
};
const translationY = new Value(0);
const veLocityY = new Value(0);
const state = new Value(State.UNDETERmineD);
const gestureHandler = onGestureEvent({ translationY,state,veLocityY });
const [] = useState(true);
const SNAP_TOP = 0;
const SNAP_BottOM = height - MINI_PLAYER_HEIGHT;
const offset = new Value(SNAP_BottOM);
const goUp: Value<0 | 1> = new Animated.Value(0);
const godown: Value<0 | 1> = new Animated.Value(0);
const translateY = clamp(
withSpring({
state,offset,value: translationY,veLocity: veLocityY,snapPoints: [SNAP_TOP,SNAP_BottOM],config: springConfig,}),SNAP_TOP,SNAP_BottOM
);
const miniPlayerOpacity = interpolate(translateY,{
inputRange: [SNAP_BottOM - MINI_PLAYER_HEIGHT,outputRange: [0,1],extrapolate: Extrapolate.CLAMP,});
const overlayOpacity = interpolate(translateY,{
inputRange: [
SNAP_BottOM - MINI_PLAYER_HEIGHT * 2,SNAP_BottOM - MINI_PLAYER_HEIGHT,],});
const clock = new Clock();
useEffect(() => {
if (audioPost && shouldLoad) {
initPlaybackInstance();
dispatch(postIsLoading());
}
},[shouldLoad]);
const initPlaybackInstance = async () => {
if (playbackInstance != null) {
playbackInstance.unloadAsync();
}
await Audio.setAudioModeAsync({
allowsRecordingIOS: false,interruptionModeIOS: Audio.INTERRUPTION_MODE_IOS_DO_NOT_MIX,playsInSilentModeIOS: true,interruptionModeAndroid: Audio.INTERRUPTION_MODE_ANDROID_DO_NOT_MIX,shouldDuckAndroid: false,staysActiveInBackground: true,playThroughEarpieceAndroid: true,});
await loadAudio();
};
const loadAudio = async () => {
const audioInstance = new Audio.sound();
const source = {
uri: storedTrackBySlug[audioPost.slug]?.uri ?? audioRoute(audioPost.slug),};
const status = {
shouldplay: true,volume: volume,};
audioInstance.setonPlaybackStatusUpdate(onPlaybackStatusUpdate);
await audioInstance.loadAsync(source,status,false);
setPlaybackInstance(audioInstance);
};
const onPlaybackStatusUpdate = (status): void => {
setIsBuffering(status.isBuffering);
setIsPlaying(status.isPlaying);
setCurrentPositionMillis(status.positionMillis);
setTotalDurationMillis(status.durationMillis);
setRate(status.rate);
};
// PERHAPS REMOVE USE CODE AND ONLY USE CLICK FROM SNACK EXAMPLE AND SWIPE FROM SPOTIFY EXAMPLE
useCode(() => {
console.log('useCode CALLED');
console.log(JSON.stringify(goUp));
return block([
cond(goUp,[
set(
offset,timing({
clock,from: offset,to: SNAP_TOP,})
),cond(not(clockRunning(clock)),[set(goUp,0)]),]),cond(godown,to: SNAP_BottOM,[set(godown,]);
},[]);
return (
<PanGestureHandler {...gestureHandler}>
<Animated.View
style={[styles.playerSheet,{ transform: [{ translateY }] }]}
>
<FullPlayer
post={audioPost}
isPlaying={isPlaying}
isBuffering={isBuffering}
currentPositionMillis={currentPositionMillis}
totalDurationMillis={totalDurationMillis}
rate={rate}
handleSkipBack={handleSkipBack}
handleSkipForward={handleSkipForward}
handlePlayPause={handlePlayPause}
seekPositionBySeconds={seekPositionBySeconds}
increaseRateByQuarter={increaseRateByQuarter}
onPress={() => {
console.log('AUdioPLAYER CLICKED');
godown.setValue(1);
}}
/>
<Animated.View
style={{
...StyleSheet.absoluteFillObject,opacity: overlayOpacity,}}
pointerEvents='none'
/>
<Animated.View
style={{
opacity: miniPlayerOpacity,position: 'absolute',top: 0,left: 0,right: 0,height: MINI_PLAYER_HEIGHT,}}
>
<MiniPlayer
postTitle={audioPost?.title}
isPlaying={isPlaying}
isBuffering={isBuffering}
handlePlayPause={handlePlayPause}
onPress={() => {
console.log('MINIAUdioPLAYER CLICKED');
goUp.setValue(1);
//setIsPlayerUp(!isPlayerUp);
}}
/>
</Animated.View>
</Animated.View>
</PanGestureHandler>
);
};
const styles = StyleSheet.create({
thumbnailoverlay: {
...StyleSheet.absoluteFillObject,padding: 16,},scroll: {
flex: 1,marginHorizontal: 10,overflow: 'hidden',playerSheet: {
...StyleSheet.absoluteFillObject,backgroundColor: 'cyan',});
export default Player;
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)